【问题标题】:Oracle 10.2.0.4.0 query on partial xpathOracle 10.2.0.4.0 对部分 xpath 的查询
【发布时间】:2017-08-28 07:29:54
【问题描述】:

我需要更改以下查询才能查询任何类型的投标项目。

/Basket/卡片TenderItem/Description

/Basket/现金TenderItem/Description

所以

/Basket/通配符TenderItem/Description

我查看了各种示例,但它们在运行时无法返回任何结果(如果可以正常工作,很高兴承认用户错误!)

SELECT 
RETURN_ID
,SALE_ID,
,extractValue(xmltype(RETURNxml),'/Basket/CashTenderItem/NetValue')
,extractValue(xmltype(RETURNxml),'/Basket/CashTenderItem/Description')
FROM SPR361
WHERE return_id = '9999.0303|20170327224954|2063'

【问题讨论】:

    标签: sql xml oracle xpath


    【解决方案1】:

    这是 SQL-Server 语法,我无法测试,如果这也适用于 Oracle,但我认为它会。你可以使用XQuery函数contains()

    DECLARE @xml XML=
    N'<root>
    <abcTenderItem>test1</abcTenderItem>
    <SomeOther>should not show up</SomeOther>
    <xyzTenderItem>test2</xyzTenderItem>
    </root>';
    
    SELECT @xml.query(N'/root/*[contains(local-name(),"TenderItem")]')
    

    仅显示名称中带有“TenderItem”的元素:

    <abcTenderItem>test1</abcTenderItem>
    <xyzTenderItem>test2</xyzTenderItem>
    

    【讨论】:

      【解决方案2】:

      如果您只想匹配以 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)
        ...
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多