我认为您需要对 XML 命名空间更加小心。
您发布的 XML 片段格式不正确,因为它没有 soap 或 ns2 命名空间的命名空间绑定。让我们添加它们,看看会发生什么:
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、issueEventType 和 id。在您的 XPath 表达式中,这些名称都位于其 URI 为空字符串的名称空间中。在您的 XML 文档中,命名空间中有名称为 return、issueEventType 和 id 的元素,其 URI 为 http://www.example.com/。由于命名空间 URI 不同,因此元素不被视为匹配。
解决此问题的方法是将另一个前缀绑定到与您绑定了默认前缀的 URI 相同的 URI,并在 XPath 表达式中使用该前缀。 extract 方法采用可选的第二个参数,该参数指定要绑定到命名空间的附加前缀,其格式与您指定将前缀绑定到 XML 中的命名空间的“属性”完全相同。而不是写
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,然后使用此前缀限定名称 return、issueEventType 和 id。如果您愿意,可以使用不同的前缀,只要您始终使用它。
你瞧,这行得通:
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.