如果您只想匹配以 TenderItem 结尾的任何内容,但之后没有任何内容,则可以通过子字符串检查来指定:
SELECT
RETURN_ID
,SALE_ID
,extractValue(xmltype(RETURNxml),
'/Basket/*[substring(name(), string-length(name()) - 9) = "TenderItem"]/NetValue')
,extractValue(xmltype(RETURNxml),
'/Basket/*[substring(name(), string-length(name()) - 9) = "TenderItem"]/Description')
FROM SPR361
WHERE return_id = '9999.0303|20170327224954|2063'
如果您在该固定字符串之后没有任何节点,那么@Shnugo 的contains 方法更容易,并且在Oracle 中会非常相似:
...
,extractValue(xmltype(RETURNxml),
'/Basket/*[contains(name(), "TenderItem")]/NetValue')
,extractValue(xmltype(RETURNxml),
'/Basket/*[contains(name(), "TenderItem")]/Description')
我不确定name() 和local-name() 之间有什么真正的区别。
如果一个篮子可以有多个子节点(卡片和现金,或者每个节点不止一个),您也可以切换到 XMLTable 语法:
SELECT
s.RETURN_ID
,s.SALE_ID
,x.netvalue
,x.description
FROM SPR361 s
CROSS JOIN XMLTable(
'/Basket/*[contains(name(), "TenderItem")]'
PASSING XMLType(s.RETURNxml)
COLUMNS netvalue NUMBER PATH './NetValue'
, description VARCHAR(80) PATh './Description'
) x
WHERE s.return_id = '9999.0303|20170327224954|2063'
这里可能有点矫枉过正,但对于更复杂的测试,您可以使用其他 XPath 语法,例如:
CROSS JOIN XMLTable(
'for $i in /Basket/*
where contains($i/name(), "TenderItem") return $i'
PASSING XMLType(s.RETURNxml)
...