这是问题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的想法?
答案 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上的提取:
原始查询的问题是表达式必须放在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
;
<强>更新强>
删除了关于XPath 1.0 / 2.0差异的句子作为问题的来源,因为表达式也适用于extract()。
来自引用问题的原始解决方案已经过验证,可以在SQLFiddle上使用extract()。
为原始查询添加了正确的变体