【问题标题】:XQuery - How to insert elements?XQuery - 如何插入元素?
【发布时间】:2015-12-01 15:38:30
【问题描述】:

我有以下 xml:

<subjects>
   <subject id="5" name="Maths"/>
   <subject id="10" name="English" points="5"/>
   <subject id="15" name="Science" points="10" cats="15"/>
</subjects>

我有以下代码:

for $subject in $subjects/subject
return 
     <subject id="{$subject/@id}">
          <foo/>
     </subject>

哪个输出

<subject id="5"><foo/></subject>
<subject id="10"><foo/></subject>
<subject id="15"><foo/></subject>

但是上面的代码并没有显示出主题的所有属性。只有id。当然,我可以继续硬编码更多属性,但如果我不知道属性名称是什么,这将无济于事。

我想要的是这样的:

<subject id="5" name="Maths"><foo/></subject>
<subject id="10" name="English" points="5"><foo/></subject>
<subject id="15" name="Science" points="10" cats="15"><foo/></subject>

我相信解决方案是这样的:

for $subject in $subjects/subject
return 
     insert-child( <foo/>, $subject)

我该怎么做?

【问题讨论】:

  • XPath 根本不支持插入;您正在做的是 XQuery,而不是 XPath。
  • 我还强烈建议阅读 XQUF(XQuery 更新工具)的文档。
  • @Charles Duffy 此功能是否仅适用于 Saxon EE saxonica.com/html/documentation/using-xquery/update.html 因为我使用的是免费社区版 (CE)
  • 我对 Saxon 不是很熟悉——我首选的 XQuery 实现是 BaseX——所以我不能一概而论。

标签: xml xquery saxon xquery-3.0


【解决方案1】:

一旦您的 XML 源变得更加复杂,如果您的任务是对大型 XML 文档进行小的更改,那么我强烈建议您使用 XSLT 而不是 XQuery。 XSLT 基于匹配模板规则的递归下降处理模型绝对适合这项任务,如果您尝试在 XQuery 中执行此操作,您最终会在您自己的递归函数中“手动”复制这种机制。

另一种选择是 XQuery 更新(为了回答您的问题,Saxon 的商业版本支持该更新)。我不是 XQuery Update 的狂热爱好者,除了可能是在数据库上下文中,但它确实可以完成这项工作,而且有些人喜欢它。

【讨论】:

  • 据我所知,XQuery 更新会自行更新原始文档。如果我只想像我在问题中显示的那样编辑我的输出怎么办。
  • @YahyaUddin 正如 Kay 博士所建议的,对于简单的任务,XQuery 可能就足够了(请参阅递归 typeswitch 模式的示例),但对于复杂的规则,XSLT 更适合该任务。跨度>
  • @YahyaUddin XQuery 更新包括一个 copy...modify(又名“transform”)表达式,它创建原始的修改副本,而不是在原地更新原始。
【解决方案2】:

你在正确的轨道上。在重写元素时,您可以简单地使用通配符属性选择器将所有属性从上下文节点复制到新构建的元素。

for $subject in $subjects/subject
return 
  <subject>{
      $subject/@*,
      <foo/>
  }</subject>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多