2014-05-15 38 views
5

Oracle 11g。我發現如果我將NOENTITYESCAPING添加到XMLELEMENT函數中,它很好地關閉了實體轉義。但是,當我將結果傳遞給EXTRACT時,轉義似乎又回來了。Oracle的EXTRACT函數是否打破了XMLELEMENT中的NOENTITYESCAPING?

select xmlelement(NOENTITYESCAPING e,id,'->') 
    from (select level as id 
      from dual 
     connect by level < 6)  

XMLELEMENT(NOENTITYESCAPINGE,ID,'->') 
--------------------------------------- 
<E>1-></E> 
<E>2-></E> 
<E>3-></E> 
<E>4-></E> 
<E>5-></E> 

現在,加入EXTRACT

select xmlelement(NOENTITYESCAPING e,id,'->').extract('//text()') 
    from (select level as id 
      from dual 
     connect by level < 6) 

XMLELEMENT(NOENTITYESCAPINGE,ID,'->').EXTRACT('//TEXT()') 
---------------------------------------------------------- 
1-&gt; 
2-&gt; 
3-&gt; 
4-&gt; 
5-&gt; 

任何修復/解決方法,以保持逃逸關掉? manual沒有幫助。

回答

11

嘗試使用extractvalue()函數,該函數使用unescape編碼的實體而不是extract()。下面是一個例子:

clear screen; 
column res format a20; 

-- depending on a situation, NOENTITYESCAPING might be dropped 

select extractvalue(
        xmlelement(NOENTITYESCAPING e,id,'->') 
        , '//text()' 
        ) as res 
    from (select level as id 
      from dual 
     connect by level < 6) 

結果:

RES     
-------------------- 
1->     
2->     
3->     
4->     
5->  

但使用extractvalue()函數可以由以下事實:它只能返回一個節點的值被限制。在返回多個節點的值的utl_i18n包,該包的unescape_reference()功能的情況下可以用於UNESCAPE編碼實體:

clear screen; 
column res format a20; 

select utl_i18n.unescape_reference(xmlelement(root 
              , xmlelement(node1, '>') 
              , xmlelement(node2, '<') 
              ).extract('//text()').getstringval() 
            ) as res 
from dual 
connect by level <= 3; 

結果:

RES     
-------------------- 
><     
><     
>< 

是的,作爲utl_i18n.unescape_reference()函數僅接受varchar2數據類型和類型的值,這些值可以隱式轉換爲varchar2數據類型,當處理大型數據類型時,您的雙手是並列的「「。在這種情況下,您可能會轉向dbms_xmlgen程序包和convert()函數,該函數具有能夠接受CLOB的重載版本。這裏有一個例子:

select dbms_xmlgen.convert(
          xmlagg(xmlelement(root 
              , xmlelement(node1, '>') 
              , xmlelement(node2, '<') 
              ) 
           ).extract('//text()').getclobval() 
          , 1) as res 
from dual 
connect by level <= 3000; -- 1 (second parameter of the convert() function) 
          -- instructs function to decode entities 

結果:

RES 
------------------------------------------------------ 
><><><><><><><><><><><><><><><><><><><><><><><><><> 
-- ... the rest of the CLOB 
+0

感謝尼古拉。我看到你更新了你的答案,因爲我只是想評論一下,因爲我使用的是XMLAGG(解決LISTAGG的4000字符限制),並且該提取值將不起作用。我試過你的建議utl_i18n.unescape_reference,但我認爲這也達到了4000字符的限制。 – TrojanName

+0

這裏是我當前的查詢,它演示了這個問題:select rtrim(xmlagg(xmlelement(e,id,' - >')。extract('// text()')order by id).GetClobVal(),',' ) from(select level from id from double connect by level <6) – TrojanName

+1

@TrojanName'我認爲那也是達到了4000個字符的限制'是的。 'unescape_reference()'函數接受'varchar2'的值。要處理「* big *」字符串,請使用'dbms_xmlgen.convert()'函數。答案已更新。 –

相關問題