XQuery 添加元素 和属性

在 XQuery 中,要向现有的 XML 文档或节点添加新元素添加属性,通常有两种主要场景:

  1. 在查询结果中构造新的元素和属性(最常见)
  2. 使用 XQuery Update Facility (XQuery Update) 真正修改原始 XML 文档(只有支持更新的处理器才行,如 BaseX、eXist-db、MarkLogic、Zorba 等)

下面分别详细说明这两种方式。

1. 构造新的元素和属性(所有 XQuery 处理器都支持)

这是最常用的方式,使用直接元素构造函数计算元素/属性构造函数

(: 假设有一个变量 $book 包含以下内容 :)
let $book := <book isbn="12345">
  <title>XPath and XQuery</title>
  <author>Priscilla Walmsley</author>
</book>

(: 方式1:直接元素构造函数(最常用):)
let $new-book := 
  <book isbn="{$book/@isbn}" category="TECH">
    {$book/*}  (: 复制原有的所有子元素 :)
    <price>49.99</price>
    <publish_date>2023-01-01</publish_date>
    <in-stock>true</in-stock>
  </book>

return $new-book

结果:

<book isbn="12345" category="TECH">
  <title>XPath and XQuery</title>
  <author>Priscilla Walmsley</author>
  <price>49.99</price>
  <publish_date>2023-01-01</publish_date>
  <in-stock>true</in-stock>
</book>

更灵活的写法(计算构造函数):

let $new-book := 
  element {"book"} {
    attribute {"isbn"} {$book/@isbn},
    attribute {"category"} {"COMPUTER"},
    attribute {"lang"} {"en"},
    $book/title,
    $book/author,
    element {"price"} {49.99},
    element {"discount"} {10}
  }
return $new-book

在已有元素中插入新元素(拷贝后修改,称为“变换”):

(: 经典的“拷贝并修改”模式 :)
let $new-book :=
  copy $b := $book
  modify (
    (: 添加属性 :)
    insert node attribute {"category"} {"WEB"} into $b,

    (: 在最后添加新元素 :)
    insert node <edition>2</edition> as last into $b,

    (: 在某个位置前/后插入 :)
    insert node <translator>张三</translator> after $b/author
  )
  return $b

return $new-book

注意:上面的 copy ... modify 语法属于 XQuery Update Facility,不是所有处理器都支持(Saxon EE 支持,Saxon PE/HE 不支持)。

2. 真正修改原始文档(XQuery Update Facility 1.0/3.0)

只有在支持更新的数据库或处理器中才能真正改变存储的 XML。

(: 假设要修改 doc("books.xml")//book[@isbn="12345"] :)
for $b in doc("books.xml")//book[@isbn="12345"]
return (
  (: 添加属性 :)
  insert node attribute category {"PROGRAMMING"} into $b,

  (: 添加子元素(作为最后一个子节点):)
  insert node <price currency="USD">59.99</price> as last into $b,

  (: 或者插入到特定位置 :)
  insert node <rating>4.8</rating> before $b/price,

  (: 同时添加多个节点 :)
  insert nodes (
    <pages>528</pages>,
    <in-stock>true</in-stock>
  ) as last into $b
)

其他常用更新语句:

(: 替换属性值 :)
replace value of node $b/@category with "COMPUTER"

(: 删除属性 :)
delete node $b/@old-attr

(: 重命名元素 :)
rename node $b/price as "list-price"

3. 常见实际例子汇总

(: 给所有没有 category 属性的 book 元素添加 category="UNKNOWN" :)
for $b in //book[not(@category)]
return insert node attribute category {"UNKNOWN"} into $b

(: 给每本书添加一个 <updated> 元素,内容是当前时间 :)
for $b in collection("books")/book
return insert node 
  <updated>{current-dateTime()}</updated> 
  as last into $b

(: 在 <book> 下已有 <title> 后立即插入 <subtitle> :)
for $b in //book
return insert node 
  <subtitle>{concat($b/title, "(第2版)")}</subtitle> 
  after $b/title

总结

需求推荐写法是否需要 Update Facility
只在查询结果中添加直接/计算元素构造函数不需要
拷贝原有节点后添加copy $x := … modify (…)需要(部分处理器支持)
真正修改存储的 XML 文档insert node … into/replace/delete 等必须支持 XQuery Update

常用支持 XQuery Update 的工具:BaseX、eXist-db、MarkLogic、Saxon EE、Zorba 等。

如果你告诉我你用的是哪个 XQuery 处理器(Saxon、BaseX、eXist-db、MarkLogic 等),我可以给出最精准的写法!

文章已创建 2783

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部