2013-08-19 120 views
1

我有我的PLSQL過程中存儲在CLOB變量下面的XML文檔:提取XML基於子元素值

<soap:Envelope> 
<soap:Body> 
<ns2:getAllIssueHistoriesResponse> 
    <return> 
     <eventDate>2013-08-02T11:45:58.013+02:00</eventDate> 
     <eventText>Test</eventText> 
     <issueEventType> 
      <id>10</id> 
      <value>Replied</value> 
     </issueEventType> 
    </return> 
    <return>...</return> 
    <return>...</return> 
</ns2:getAllIssueHistoriesResponse> 
</soap:Body> 
</soap:Envelope> 

我想提取都返回節點和10 issueEventType值。

我已經習慣了下面的代碼,試圖做到這一點,其中p_xml_content是包含我的CLOB XML:

l_xml_parser := '<?xml version="1.0" encoding="UTF-8"?><results>'; 
l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//return/issueEventType/[id=10]').getclobval()); 
l_xml_parser := l_xml_parser ||'</results>'; 

這不返回任何儘管在xml文檔中肯定是一個值爲10的issueEventType。返回

l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//return/issueEventType[id=''10'']').getclobval()); 

而且

l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//return/issueEventType/[@id=''10'']').getclobval()); 

,但仍然沒有:

我已經與多種變化,如試過這樣。

任何想法?

回答

0

的這裏的問題是與XPATH定義。有些東西正在返回,但這不是我所期望的。我希望包含該id的整個返回節點作爲子節點。要返回此項,需要以下內容:

l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//return/issueEventType/[id=10] /../.').getclobval()); 

/../。在XPATH中告訴聲明,當它發現並且id爲10時,它需要向父級上升1級。由於當前節點是issueEventType,因此我們需要返回標記。但是,我們需要定義/。告訴XPATH檢索返回節點中的當前節點。這將返回正確的返回節點以及它們包含的所有節點。

+0

您可以稍微簡化XPath:'// return [issueEventType/id = 10]'也應該可以工作。 –

3

我認爲你需要對XML名稱空間更小心。

您發佈的XML片段格式不正確,因爲它沒有soapns2名稱空間的名稱空間綁定。讓我們把它們加進來看看會發生什麼:

SQL> SET SERVEROUTPUT ON 
SQL> 
SQL> DECLARE 
    2  p_xml_content VARCHAR2(32767) := '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://www.your-url.com/"> 
    3 <soap:Body> 
    4 <ns2:getAllIssueHistoriesResponse> 
    5  <return> 
    6   <eventDate>2013-08-02T11:45:58.013+02:00</eventDate> 
    7   <eventText>Test</eventText> 
    8   <issueEventType> 
    9    <id>10</id> 
10    <value>Replied</value> 
11   </issueEventType> 
12  </return> 
13  <return>...</return> 
14  <return>...</return> 
15 </ns2:getAllIssueHistoriesResponse> 
16 </soap:Body> 
17 </soap:Envelope>'; 
18 
19 l_xml_parser  VARCHAR2(32767); 
20 BEGIN 
21 l_xml_parser := '<?xml version="1.0" encoding="UTF-8"?><results>'; 
22 l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//return/issueEventType[id=10]').getclobval()); 
23 l_xml_parser := l_xml_parser ||'</results>'; 
24 
25 dbms_output.put_line(l_xml_parser); 
26 
27 END; 
28/
<?xml version="1.0" encoding="UTF-8"?><results><issueEventType> 
    <id>10</id> 

<value>Replied</value> 
</issueEventType> 
</results> 

PL/SQL procedure successfully completed. 

這一切似乎都奏效。我們得到了一些輸出。那麼你怎麼沒有收到?

恐怕我不得不在這裏猜測。鑑於您已經從XML文檔中省略了兩個名稱空間綁定,我將假定您至少省略了一個名稱空間綁定,並且在您省略的那些綁定默認名稱空間前綴給非 - 空的URL。 (換句話說,你的XML文檔有一個看起來像xmlns="..."的屬性。)如果我們把這個命名空間綁定添加到你的XML文檔中會發生什麼?

SQL> DECLARE 
    2  p_xml_content VARCHAR2(32767) := '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://www.your-url.com/" xmlns="http://www.example.com/"> 
    3 <soap:Body> 
    4 <ns2:getAllIssueHistoriesResponse> 
    5  <return> 
    6   <eventDate>2013-08-02T11:45:58.013+02:00</eventDate> 
    7   <eventText>Test</eventText> 
    8   <issueEventType> 
    9    <id>10</id> 
10    <value>Replied</value> 
11   </issueEventType> 
12  </return> 
13  <return>...</return> 
14  <return>...</return> 
15 </ns2:getAllIssueHistoriesResponse> 
16 </soap:Body> 
17 </soap:Envelope>'; 
18 
19 l_xml_parser  VARCHAR2(32767); 
20 BEGIN 
21 l_xml_parser := '<?xml version="1.0" encoding="UTF-8"?><results>'; 
22 l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//return/issueEventType[id=10]').getclobval()); 
23 l_xml_parser := l_xml_parser ||'</results>'; 
24 
25 dbms_output.put_line(l_xml_parser); 
26 
27 END; 
28/
DECLARE 
* 
ERROR at line 1: 
ORA-30625: method dispatch on NULL SELF argument is disallowed 
ORA-06512: at line 22 

很明顯,這沒有奏效。

這裏發生的事情是致電extract返回NULL。你不能在NULL上撥打getclobval(),這就是你的ORA-30625錯誤。對extract的調用返回NULL,因爲沒有與您的XPath表達式匹配。

XPath表達式中的非限定名稱(即無前綴)名稱始終爲引用「默認」名稱空間中的名稱。你有三個這樣的名字,return,issueEventTypeid。在您的XPath表達式中,這些名稱全部位於URI爲空字符串的名稱空間中。在XML文檔中,名稱空間中的名稱爲return,issueEventTypeid的元素的URI爲http://www.example.com/。由於命名空間URI不同,因此不認爲這些元素是匹配的。

解決此問題的方法是將另一個前綴綁定到與默認前綴綁定到的URI相同的URI,並在您的XPath表達式中使用該前綴。 extract方法採用可選的第二個參數,該參數指定要綁定到名稱空間的其他前綴,並且其格式與您指定用於將前綴綁定到XML中的名稱空間的'attributes'完全相同。而不是寫

l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//return/issueEventType[id=10]').getclobval()); 

l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//e:return/e:issueEventType[e:id=10]', 'xmlns:e="http://www.example.com/"').getclobval()); 

這裏,我們前綴e綁定到相同的URI爲綁定到默認前綴,然後纔有資格參加的名字returnissueEventTypeid與此字首。如果您願意,您可以使用不同的前綴,只要您一致地使用它即可。

瞧,這個工程:

SQL> DECLARE 
    2  p_xml_content VARCHAR2(32767) := '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://www.your-url.com/" xmlns="http://www.example.com/"> 
    3 <soap:Body> 
    4 <ns2:getAllIssueHistoriesResponse> 
    5  <return> 
    6   <eventDate>2013-08-02T11:45:58.013+02:00</eventDate> 
    7   <eventText>Test</eventText> 
    8   <issueEventType> 
    9    <id>10</id> 
10    <value>Replied</value> 
11   </issueEventType> 
12  </return> 
13  <return>...</return> 
14  <return>...</return> 
15 </ns2:getAllIssueHistoriesResponse> 
16 </soap:Body> 
17 </soap:Envelope>'; 
18 
19 l_xml_parser  VARCHAR2(32767); 
20 BEGIN 
21 l_xml_parser := '<?xml version="1.0" encoding="UTF-8"?><results>'; 
22 l_xml_parser := l_xml_parser ||(xmltype(p_xml_content).extract('//e:return/e:issueEventType[e:id=10]', 'xmlns:e="http://www.example.com/"').getclobval()); 
23 l_xml_parser := l_xml_parser ||'</results>'; 
24 
25 dbms_output.put_line(l_xml_parser); 
26 
27 END; 
28/
<?xml version="1.0" encoding="UTF-8"?><results><issueEventType 
xmlns="http://www.example.com/"> 
    <id>10</id> 

<value>Replied</value> 
</issueEventType> 
</results> 

PL/SQL procedure successfully completed. 
+0

恐怕這是不正確的。至少在我的情況下。命名空間在那裏。請參閱下面的解決方案這實際上是xpath的錯誤。 – jezzipin

+0

@jezzipin:所以你對沒有被返回的評論是錯誤的?如果你要問一個沒有準確描述你的問題的問題,那就期待錯誤的答案。 –