2012-10-22 97 views
7

我遇到了Oracle SQL和XML問題。在Oracle SQL中解析帶有未知名稱空間的XML

我將從外部系統獲取大量格式良好的XML數據的clobs,以解析,解釋和填充一些表格。我使用XMLTable編寫了一個解決方案,該解決方案以xml clob列的形式放置在表格的視圖中,還有一些審計信息和內容(我希望以這種方式保留)。

NAMESPACES給我做惡夢。顯然我不能把它們放在xmlnamespaces子句中,因爲我永遠不知道它們將會是什麼。荒謬!交付的相同類型的項目可能會在不同的時間點具有不同的名稱空間。沒有有限的列表。甚至沒有默認的xmlns是不變的。

到目前爲止,我提出的最佳工作解決方案是一組regexp_replace(準確地說是3),在解析之前擦除所有命名空間。但是,性能是一個巨大的問題。

肯定有東西聰明我失蹤了?

+0

你有你的代碼,以便我們可以更好地幫助你嗎? – justderb

+0

Oracle強制執行安全性並停止對外部XML模式URL的任何調用,這意味着所有有效模式都需要使用DBMS_XMLSCHEMA(註冊模式)在數據庫中進行註冊,因此很多模式已經在DB中註冊。但是,如果他們不是,那麼您必須從所有第三方(發送XML)中獲得它們的列表並將它們註冊到Oracle中。 – Annjawn

回答

5

我知道這是非常古老的,但我今天發現它,並記住我嘗試處理名稱空間XML時遇到的痛苦。我的解決方案是用XSLT轉換去除命名空間,並將其作爲普通的舊XML進行處理。我用來做到這一點的功能是:

function remove_namespace(i_xml in xmltype) 
    return xmltype 
is 
    v_xml xmltype default i_xml; 
    v_xsl varchar2(32767); 
begin 
    v_xsl := '<?xml version="1.0" encoding="UTF-8"?> 
     <xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
     <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
     <xsl:template match="*"> 
      <!-- remove element prefix (if any) --> 
      <xsl:element name="{local-name()}"> 
      <!-- process attributes --> 
      <xsl:for-each select="@*"> 
      <!-- remove attribute prefix (if any) --> 
      <!-- this if filters out any xmlns="" atts that have no 
       namespace prefix in the xml --> 
      <xsl:if test="(local-name() != ''xmlns'')"> 
       <xsl:attribute name="{local-name()}"> 
       <xsl:value-of select="."/> 
       </xsl:attribute> 
      </xsl:if> 
      </xsl:for-each> 
     <xsl:apply-templates/> 
     </xsl:element> 
     </xsl:template> 
     </xsl:stylesheet>'; 
    return v_xml.transform(xmltype(v_xsl)); 
end;