gpt4 book ai didi

sql - 基于子元素值使用 PLSQL 提取 XML

转载 作者:行者123 更新时间:2023-12-03 17:15:39 25 4
gpt4 key购买 nike

我在 PLSQL 过程中的一个 clob 变量中存储了以下 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>

我正在尝试提取所有 issueEventType 值为 10 的返回节点。

我习惯于遵循代码来尝试实现这一点,其中 p_xml_content 是我的包含 xml 的 clob:
 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());

但仍然没有返回任何内容。

有任何想法吗?

最佳答案

我认为您需要对 XML 命名空间更加小心。

您发布的 XML 片段格式不正确,因为它没有 soap 的 namespace 绑定(bind)。也不是 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 文档中省略了两个命名空间绑定(bind),我将假设您至少又省略了一个,并且在您省略的那些中,一个将默认命名空间前缀绑定(bind)到非- 空 URL。 (换句话说,您的 XML 文档有一个看起来像 xmlns="..." 的属性。)如果我们将此命名空间绑定(bind)添加到您的 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 .你不能再调用 getclobval()NULL ,这就是给你 ORA-30625 错误的原因。调用 extract返回 NULL因为没有任何东西与您的 XPath 表达式匹配。

XPath 表达式中的非限定(即无前缀)名称始终引用“默认”命名空间中的名称。你有三个这样的名字, return , issueEventTypeid .在您的 XPath 表达式中,这些名称都位于其 URI 为空字符串的 namespace 中。在您的 XML 文档中,您有名称为 return 的元素。 , issueEventTypeid在具有 URI http://www.example.com/ 的命名空间中.因为命名空间 URI 不同,所以元素不被认为是匹配的。

解决此问题的方法是将另一个前缀绑定(bind)到与您绑定(bind)了默认前缀的 URI 相同的 URI,并在 XPath 表达式中使用该前缀。 extract方法接受一个可选的第二个参数,该参数指定绑定(bind)到命名空间的附加前缀,其格式与您指定将前缀绑定(bind)到 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());

在这里,我们绑定(bind)前缀 e与绑定(bind)到默认前缀的 URI 相同,然后我们限定名称 return , issueEventTypeid带有这个前缀。如果您愿意,可以使用不同的前缀,只要您始终使用它。

瞧,这行得通:

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.

关于sql - 基于子元素值使用 PLSQL 提取 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18318657/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com