Oracle XPath:选择第一次出现的元素

时间:2015-04-09 17:01:34

标签: xml oracle xpath

这是问题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>

我尝试在book下选择属性为category的{​​{1}}的第一次出现。对于上述数据,应返回location="US"

建议的解决方案B2不起作用 它返回以下错误:(/bookstore/category/book[@location='US'])[1]
这是一个SQL Fiddle来证明这个问题。

如何使解决方案适应Oracle对XPath的想法?

2 个答案:

答案 0 :(得分:3)

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

您可以使用谓词来检查是否存在具有相同属性值的任何preceding::书籍元素(按文档顺序)。事实上,我几乎倾向于说这是唯一有效的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

答案 1 :(得分:1)

没有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. 为原始查询添加了正确的变体