【问题标题】:Oracle XPath: Selecting first occurrence of an elementOracle XPath:选择第一次出现的元素
【发布时间】:2015-06-15 04:22:23
【问题描述】:

这是对问题 XPath: Select first element with a specific attribute 的扩展,专门针对 Oracle。

假设我们在名为xml_data 的列中有以下数据:

<bookstore>
 <category>
  <book location="CAN">A1</book>
  <book location="FIN">A2</book>
 </category>
 <category>
  <book location="FIN">B1</book>
  <book location="US">B2</book>
 </category>
 <category>
  <book location="US">C2</book>
  <book location="FIN">C1</book>
 </category>
</bookstore>

我正在尝试选择categorybook 属性location="US" 的第一个匹配项。对于上述数据,应该返回B2

建议的解决方案 (/bookstore/category/book[@location='US'])[1] 不起作用。
它返回以下错误:ORA-19110: unsupported XQuery expression
这是一个 SQL Fiddle 演示问题。

如何使解决方案适应 Oracle 的 XPath 理念?

【问题讨论】:

    标签: xml oracle xpath


    【解决方案1】:

    很遗憾,Oracle 不支持这种路径表达式。您应该考虑提交错误报告。

    您可以使用谓词来检查是否存在具有相同属性值的preceding:: book 元素(按文档顺序)。事实上,我几乎倾向于说这是唯一有效的仅 XPath 方法。

    SELECT
        parsed.book
    FROM xml_test x,
    XMLTABLE(
      '/bookstore' PASSING XMLTYPE(x.xml_data)
      COLUMNS
        "BOOK" VARCHAR2(16) PATH '/bookstore/category/book[@location="US"][not(preceding::book[@location = "US"])]'
    ) parsed
    ;
    

    这会产生想要的结果:

    BOOK - B2
    

    【讨论】:

    • 啊,我是如此接近,你打败了我。你认为 preceeding::axis 会比我想出的使用 count 的方法更好吗?
    • @DanField 您的解决方案之所以有效,是因为第一个带有@location="US"book 元素意外地是其父元素的第二个子元素。尝试更改输入 XML,看看会发生什么。如果两本美国书籍都是其父母的第一个孩子,则您的表达式不返回任何内容。
    • 是的,我现在明白了。谢谢。
    【解决方案2】:

    没有 XQuery 的棘手方法(只是为了好玩):

    select 
      extract(extract(xml_data,'/bookstore/category/book[@location="US"]'),'/*[1]')
    from ...
    

    使用 XQuery 的解决方案适用于来自引用问题的表达式:

    select  
      XMLQuery(
        '($xdata/bookstore/category/book[@location="US"])[1]'
        passing xml_data as "xdata"
        returning content
      )
    from ...
    

    对我来说,原始表达式也适用于 SQL Fiddle 上的提取:

    SQLFiddle example

    原始查询的问题是表达式必须放在 XQuery 本身,而不是字段提取路径中。表达还可以:

    SELECT
        parsed.book
    FROM xml_test x,
    XMLTABLE(
      '(/bookstore/category/book[@location="US"])[1]' PASSING XMLTYPE(x.xml_data)
      COLUMNS
        "BOOK" VARCHAR2(16) PATH '/book'
    ) parsed
    ;
    

    更新:

    1. 删除了关于 XPath 1.0 / 2.0 差异作为问题根源的句子,因为表达式也适用于 extract()。

    2. 来自引用问题的原始解决方案已验证可与 SQLFiddle 上的 extract() 一起使用。

    3. 为原始查询添加了正确的变体

    【讨论】:

    • 有趣。但是没有 XPath 1.1,只有 XPath 1.0、2.0 和 3.0。 XMLQuery 真的意味着 XQuery,还是意味着评估路径表达式?此外,我不确定您所说的“使用 XQuery 的解决方案适用于引用问题的表达式,因为”是什么意思 - (...)[1] 行的表达式也适用于 XPath 1.0。
    • XMLQuery 是 Oracle functions to work with XML 之一,并在 XMLType 值上调用 XQuery。
    • 奇怪,为什么 (path)[1] 符号在 XMLQuery 中有效,但在 XMLTable 中无效?
    • 对不起所有评论者,更新答案:请查看新变体。特别感谢@MathiasMüller 提出正确的问题。
    猜你喜欢
    • 2021-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-26
    • 2011-06-05
    • 1970-01-01
    • 2012-03-23
    相关资源
    最近更新 更多