我正在尝试使用Oracle从以下XML中提取字段:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:check xmlns:ns2="http://soap.com" xmlns="http://soap.com/xsd">
<ns2:request>
<orderIDs>201902281425597269</orderIDs>
</ns2:request>
</ns2:check>
</soap:Body>
</soap:Envelope>
我尝试了以下内容及其变体,但没有运气:
..
XMLTable(XMLNAMESPACES (
'http://soap.com/xsd' AS "ns2"
),
'for $i in //orderIDs return $i'
passing XMLType(sm.REQUEST_XML)
columns "ORDER_ID" VARCHAR2(500) path '/') xt_orderid
..
以上是查询与其他表交叉连接的一部分。什么都不起作用,因为查询没有返回结果,所以我猜XMLTable命令变成空的。
非常类似的提取命令可用于响应,但是响应的结构不同。
答案 0 :(得分:1)
您使用错误的路径声明了ns2
,但无论如何您都没有引用它;由于orderIds
没有命名空间前缀,因此您需要声明一个默认值(或同样):
XMLTable(XMLNAMESPACES (
default 'http://soap.com/xsd', 'http://soap.com' AS "ns2"
),
'for $i in //orderIDs return $i'
passing XMLType(sm.REQUEST_XML)
columns "ORDER_ID" VARCHAR2(500) path '/') xt_orderid
这里也不需要for
,可以使用更简单的路径;在CTE中使用示例数据进行演示:
with sm (request_xml) as (
select '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:check xmlns:ns2="http://soap.com" xmlns="http://soap.com/xsd">
<ns2:request>
<orderIDs>201902281425597269</orderIDs>
</ns2:request>
</ns2:check>
</soap:Body>
</soap:Envelope>' from dual
)
select xt_orderid.order_id
from sm
cross join
XMLTable(XMLNAMESPACES (
default 'http://soap.com/xsd'
),
'//orderIDs'
passing XMLType(sm.REQUEST_XML)
columns "ORDER_ID" VARCHAR2(500) path '/') xt_orderid
/
ORDER_ID
--------------------------------------------------
201902281425597269
您还可以通配符命名空间,但这并不理想,通常,如果静态的话,我宁愿给出完整路径(为每个节点提供适当的命名空间)。而且,如果您的XML仅具有一个订单ID,则可以使用XMLQuery代替XMLTable,但是我想您真的会从更大的文档中提取其他信息。