XMLTable 查询 returns 无结果

XMLTable query returns no result

我对 XML 只是略微熟悉。我需要解析来自 SOAP 请求的响应。通过大量搜索,我开发了以下查询来尝试提取状态。最后,我想从响应中获取状态、cntr 和 cntr_status 字段。我的查询没有给出错误,但也没有结果。我犯了什么菜鸟错误?

SELECT *
  FROM XMLTABLE (
         XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
                       'http://www.w3.org/2001/XMLSchema' as "xsd",
                       'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
                       'http://service.xxx.com/' AS "xxx"),
                       '/soapenv:Envelope/soapenv:Body/xxx:sendDataResponse/xxx:sendDataReturn/xxx:result'
         PASSING XMLTYPE('<?xml version="1.0" encoding="UTF-8"?>' ||
                         '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ' ||
                         '                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' ||
                         '                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' ||
                         '  <soapenv:Body>' ||
                         '    <sendDataResponse xmlns="http://service.xxx.com">' ||
                         '      <sendDataReturn>' ||
                         '        <result>' ||
                         '          <build>Build 1</build>' ||
                         '          <status>SUCCESS</status>' ||
                         '          <cntr_statuses>' ||
                         '            <cntr_result>' ||
                         '              <cntr>1234567890A</cntr><cntr_status>SUCCESS</cntr_status>' ||
                         '            </cntr_result>' ||
                         '            <cntr_result>' ||
                         '              <cntr>1234567890B</cntr><cntr_status>SUCCESS</cntr_status>' ||
                         '            </cntr_result>' ||
                         '          </cntr_statuses>' ||
                         '        </result>' ||
                         '      </sendDataReturn>' ||
                         '    </sendDataResponse>' ||
                         '  </soapenv:Body>' ||
                         '</soapenv:Envelope>')
         COLUMNS status VARCHAR2(20) PATH 'xxx:status')  xmlstuff ;

来自服务的示例响应被硬编码到 XMLTYPE 函数中。

我已经尝试了任意数量的涉及 xxx 命名空间的查询字符串和列路径,都没有产生任何结果。

可能有数百个 cntr 和 cntr_status 对。

感谢观看!

使用 DEFAULT 命名空间(因为您没有为 http://service.xxx.com 定义前缀)并删除对 xxx: 的引用似乎有效:

SELECT *
FROM XMLTABLE (
       XMLNAMESPACES(
         'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
         'http://www.w3.org/2001/XMLSchema' as "xsd",
         'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
         DEFAULT 'http://service.xxx.com'
       ),
       '/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result'
       PASSING XMLTYPE(
         '<?xml version="1.0" encoding="UTF-8"?>' ||
         '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ' ||
         '                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' ||
         '                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' ||
         '  <soapenv:Body>' ||
         '    <sendDataResponse xmlns="http://service.xxx.com">' ||
         '      <sendDataReturn>' ||
         '        <result>' ||
         '          <build>Build 1</build>' ||
         '          <status>SUCCESS</status>' ||
         '          <cntr_statuses>' ||
         '            <cntr_result>' ||
         '              <cntr>1234567890A</cntr><cntr_status>SUCCESS</cntr_status>' ||
         '              <cntr>1234567890B</cntr><cntr_status>SUCCESS</cntr_status>' ||
         '            </cntr_result>' ||
         '          </cntr_statuses>' ||
         '        </result>' ||
         '      </sendDataReturn>' ||
         '    </sendDataResponse>' ||
         '  </soapenv:Body>' ||
         '</soapenv:Envelope>'
)

sqlfiddle here


然后得到第一个cntrcntr_status

SELECT *
FROM XMLTABLE (
       XMLNAMESPACES(
         'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
         'http://www.w3.org/2001/XMLSchema' as "xsd",
         'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
         DEFAULT 'http://service.xxx.com'
       ),
       '/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result'
       PASSING XMLTYPE(
         '<?xml version="1.0" encoding="UTF-8"?>' ||
         '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ' ||
         '                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' ||
         '                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' ||
         '  <soapenv:Body>' ||
         '    <sendDataResponse xmlns="http://service.xxx.com">' ||
         '      <sendDataReturn>' ||
         '        <result>' ||
         '          <build>Build 1</build>' ||
         '          <status>SUCCESS</status>' ||
         '          <cntr_statuses>' ||
         '            <cntr_result>' ||
         '              <cntr>1234567890A</cntr><cntr_status>SUCCESS</cntr_status>' ||
         '              <cntr>1234567890B</cntr><cntr_status>SUCCESS</cntr_status>' ||
         '            </cntr_result>' ||
         '          </cntr_statuses>' ||
         '        </result>' ||
         '      </sendDataReturn>' ||
         '    </sendDataResponse>' ||
         '  </soapenv:Body>' ||
         '</soapenv:Envelope>'
)
  COLUMNS
    status      VARCHAR2(20) PATH 'status',
    cntr        VARCHAR2(20) PATH 'cntr_statuses/cntr_result/cntr[1]',
    cntr_status VARCHAR2(20) PATH 'cntr_statuses/cntr_result/cntr_status[1]'
)  xmlstuff;

sqlfiddle here


更新 XML 格式

理想情况下,您应该能够在 XMLTABLE 中使用 XPATH '/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result/cntr_status/cntr_result',然后使用路径 ./../../status 获取 status;但是,在尝试遍历父元素时我一直得到 null 值,但找不到有效的解决方案。

SELECT x.*
FROM   table_name t
       CROSS JOIN
       XMLTABLE(
         XMLNAMESPACES(
           'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
           'http://www.w3.org/2001/XMLSchema' as "xsd",
           'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
           DEFAULT 'http://service.xxx.com'
         ),
         '/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result/cntr_statuses/cntr_result'
         PASSING XMLTYPE(t.xml)
         COLUMNS
           status      VARCHAR2(20) PATH './../../status',
           cntr        VARCHAR2(20)  PATH 'cntr',
           cntr_status VARCHAR2(20)  PATH 'cntr_status'
       ) x;

sqlfiddle here

根据 ,它将在 Oracle 11.2.0.4 中运行,但如果您在 Oracle 11.2.0.2 中尝试,则 status 将是 NULL(这是看到的结果在 SQLFiddle 上)。


相反,对于多个 cntr_result 元素,您可以使用两个 XMLTABLE:

SELECT x.status,
       c.cntr,
       c.cntr_status
FROM   table_name t
       CROSS JOIN
       XMLTABLE(
         XMLNAMESPACES(
           'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
           'http://www.w3.org/2001/XMLSchema' as "xsd",
           'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
           DEFAULT 'http://service.xxx.com'
         ),
         '/soapenv:Envelope/soapenv:Body/sendDataResponse/sendDataReturn/result'
         PASSING XMLTYPE(t.xml)
         COLUMNS
           status        VARCHAR2(20) PATH 'status',
           cntr_statuses XMLTYPE      PATH 'cntr_statuses'
       ) x
       CROSS JOIN
       XMLTABLE(
         XMLNAMESPACES(
           'http://schemas.xmlsoap.org/soap/envelope/' as "soapenv",
           'http://www.w3.org/2001/XMLSchema' as "xsd",
           'http://www.w3.org/2001/XMLSchema-instance' as "xsi",
           DEFAULT 'http://service.xxx.com'
         ),
         '/cntr_statuses/cntr_result'
         PASSING x.cntr_statuses
         COLUMNS
           cntr        VARCHAR2(20) PATH 'cntr',
           cntr_status VARCHAR2(20) PATH 'cntr_status'
       ) c;

假设您的数据在 table_name table 的 xml 列中。

则输出为:

STATUS CNTR CNTR_STATUS
SUCCESS 1234567890A SUCCESS
SUCCESS 1234567890B SUCCESS

sqlfiddle here