如何获取子元素但不包括它们的子代?

6
使用MarkLogic,但这可能是一个通用的XQuery问题。
我有:
<library>
  <books>
    <book title="whatever">
      <publisher>Random</publisher>
      ....more children
    </book>
    <book title="another">
      <publisher>Simon</publisher>
      ....more children
    </book>
    ...
  </books>
</library>

我希望能够返回所有具有 title 属性的 [book] 元素,但我不想获取 book 的任何子元素,例如 [publisher]。如何以正统且高效的方式实现这一目标?
相关问题:有时我可能只想获取某些子元素,而不是全部子元素,例如获取所有 book 元素及其 publisher 子元素,但不获取其他子元素。
谢谢。
4个回答

5
XQuery(实际上是XQuery的子集XPath)/library/books/book 可以做到你想要的-它返回一组书籍元素,而且仅有这些。一些API将返回对书籍元素的引用,并留给您决定如何处理它们,例如显示它们的标题。但是,许多工具和API将复制这些书籍元素以及整个以书籍为根的子树,对于数据库来说,这往往是从服务器传输到客户端的结果。在这种情况下,您不想选择现有的书籍元素,而是要构造一个包含书籍元素中信息子集的新文档。要做到这一点,可以在XQuery中使用元素构造器:
for $b in /library/books/book
return <book title="{$b/@title}"/>

1
谢谢Michael!在看过其他建议后,我认为这似乎是最优雅的方法。 - bethesdaboys

2

可能有更简单的方法...但我认为像这样复制属性而不包括其他子元素。警告:代码未经测试

for $i in doc()//book
return <book>{
    for $a in $i/@*
    return $a
}</book>

谢谢,这很有帮助,因为它为我提供了更一般化方法的感觉。 - bethesdaboys

1

我认为比Michael Kay的稍微更好的解决方案是不枚举每个所需属性,使其稍微更通用。需要注意的是/@返回的是属性而不仅仅是文本。

例如:

for $book in /library/books/book return <book>{$book/@*}</book>

甚至更一般地说:

for $book in /library/books/book return element book {$book/@*}

2
你也不必使用for循环。你可以像这样使用路径表达式: /library/books/book/<book>{@*}</book> - Evan Lenz
我确实喜欢这种方法的简单性。然而,我的第一反应是为什么你在你的x-path中有一个元素?我想我会采用这种方法。谢谢。 - Walt

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接