【问题标题】:XQuery - Returning the whole document, not just selected/modified partsXQuery - 返回整个文档,而不仅仅是选定/修改的部分
【发布时间】:2023-04-11 03:23:01
【问题描述】:

我正在尝试对 xml 文档中的某些元素进行操作,而不丢弃文档的其余部分。例如,输入

即如果我有

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <inventory><books>2</books></inventory>
  <bookList>
    <book category="COOKING">
      <title lang="en">Everyday Italian</title>
      <stock>1</stock>
    </book>
    <book category="CHILDREN">
      <title lang="en">Harry Potter</title>
      <stock>0</stock>
    </book>
    <book category="WEB">
      <title lang="en">XQuery Kick Start</title>
      <stock>1</stock>
    </book>
    <book category="WEB">
      <title lang="en">Learning XML</title>
      <stock>0</stock>
    </book>
  </bookList>
</bookstore>

并且只想展示库存书籍(即)

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <inventory><books>2</books></inventory>
  <bookList>
    <book category="COOKING">
      <title lang="en">Everyday Italian</title>
      <stock>1</stock>
    </book>
    <book category="WEB">
      <title lang="en">XQuery Kick Start</title>
      <stock>1</stock>
    </book>
  </bookList>
</bookstore>

我知道我可以明确地查询文档的其他部分并将它们组合在一起,但这是大量的样板文件,并且对于文档格式的更改很脆弱。有更好的方法吗?

我应该澄清一下,我想保留的 bookList 部分上方的 xml 文件可能还有未知的附加部分。 换句话说,我不想说我是制作一个新的&lt;bookstore&gt; 并包含&lt;inventory&gt;。我宁愿说我想包含源文档中的所有内容,但 &lt;stock&gt; 值为 0 的书籍除外。此外,如果 &lt;bookstore&gt; 元素包含附加信息,即 &lt;bookstore Name="David's Books" schema="www.bookLlist.org"&gt; 等,则同样应保留附加信息.

【问题讨论】:

  • 您的示例不是格式良好的 XML。请编辑您的问题。
  • 感谢 Ken 和 Mathias,对于这个混乱的问题,我已经更新了问题。你是对的,糟糕的 xml 让我的问题更令人困惑,更没用。感谢您的反馈。
  • 顺便说一句,这个问题仍然比它需要的要大得多。如果您不介意,我可能会尝试将其简化为基本要素,以提供如何构建良好 MCVE(最小、完整、可验证的示例)的示例。
  • 您可以尝试使用 XSLT。它将允许生成具有特定过滤器/规则的其他 xml w3schools.com/xsl/default.asp w3schools.com/xsl/xsl_if.asp

标签: xml rest xpath xquery basex


【解决方案1】:

已更新以支持任意元素。

我认为这个用例非常适合普通 XQuery:

xquery version "1.0";

let $doc := fn:doc($uri)/bookstore
return
  element bookstore {
    $doc/* except $doc/bookList,
    element bookList {
      $doc/bookList/* except
        $doc/bookList/book[xs:integer(stock) eq 0]
    }
  }

这将重建文档,除了book 元素之外的每个元素都具有stock 子元素等于0。

删除了现在不相关的例子...

【讨论】:

  • 感谢您的建议。如果我理解您的更正(并且我承认我可能不会),这需要我知道 bookList 上方的文档中还包含什么。换句话说,如果我有另一组称为 CDlist 的元素,我必须指定它才能将其包含在输出中。 (请参阅我对上面原始问题的粗体补充)。
  • 我已经用一个完全通用的解决方案更新了这个问题。注意:XQuery 3.0 示例不满足这些要求,而且看起来不再合适。
  • 您能否具体说明我的基于 XQUF 的答案如何不符合给定的要求? (也许作为对该答案的评论,因此它的局限性对于考虑它的人来说更加明显)。
  • 对不起,我不是故意的。我的意思是 my XQuery 3.0 示例(local:projection() 等)不再符合要求。为了清楚起见,我把它留了下来,但它增加了混乱,所以我把它拿下来了。我认为您的基于 XQUF 的答案没有任何问题;我只是更喜欢显式转换。
【解决方案2】:

XQUF (the XQuery Update Facility) 让这一切变得简单:

copy $c := doc('your-database')      (: select top of the document you want to return :)
modify delete node $c//book[stock=0] (: make changes you want :)
return $c                            (: return the whole document :)

使用copy 使其成为非更新表达式,因此它不会修改您的原始数据源。

(XQUF is a W3C recommendation;但是,并非所有 XQuery 引擎都支持它;BaseX 是早期采用者)。

【讨论】:

  • 感谢您的建议。我会试一试的。
  • @DavidK,我在原来的答案中发现了一个小错误——//book 必须是$c//book;如果遇到问题,请重试。
猜你喜欢
  • 1970-01-01
  • 2018-06-08
  • 2019-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 2018-04-29
  • 1970-01-01
相关资源
最近更新 更多