我有一个 XML 文件:
<xml>
<title>Moby-Dick</title>
<author>Herman Melville</author>
<title>Sunrise Nights</title>
<author>Jeff Zentner</author>
<author>Brittany Cavallaro</author>
<price>14.52€</price>
<title>My Salty Mary</title>
<author>Cynthia Hand</author>
<author>Brodi Ashton</author>
<author>Jodi Meadows</author>
</xml>
我想将其转变为:
<xml>
<book>
<title>Moby-Dick</title>
<author>Herman Melville</author>
</book>
<book>
<title>Sunrise Nights</title>
<author>Jeff Zentner</author>
<author>Brittany Cavallaro</author>
<price>14.52€</price>
</book>
<book>
<title>My Salty Mary</title>
<author>Cynthia Hand</author>
<author>Brodi Ashton</author>
<author>Jodi Meadows</author>
</book>
</xml>
逻辑是每次遇到
book
时创建一个新的 title
并将所有后续节点放入该书中。
这是我迄今为止尝试过的:
let $books := (
doc("books.xml")/xml/* => fold-left((array{}, 0), function($acc, $node) {
let $arr := $acc[1], $idx := $acc[2] return
if (name($node) = "title")
then ($arr => array:append($node), $idx+1)
else ($arr => array:put($idx, ($arr => array:get($idx), $node)), $idx)
})
)[1] return
<xml>{for $book in $books return <book>{$book}</book>}</xml>
但是我明白了
<xml>
<book>
<title>Moby-Dick</title>
<author>Herman Melville</author>
<title>Sunrise Nights</title>
<author>Jeff Zentner</author>
<author>Brittany Cavallaro</author>
<price>14.52€</price>
<title>My Salty Mary</title>
<author>Cynthia Hand</author>
<author>Brodi Ashton</author>
<author>Jodi Meadows</author>
</book>
</xml>
旁白:
group by
似乎对解决当前问题没有用,所以我尝试“手动”对书籍进行分组,但我不知道这是否是正确的方法;欢迎任何提示。
如果您可以选择使用 XSLT 2.0+,这非常简单:
<xsl:template match="booke" group-starting-with="title">
<book>
<xsl:copy-of select="current-group()"/>
</book>
</xsl:template>
在 XQuery 3.1 中,可以使用 FLWOR
window
子句来完成。
for tumbling window $w in books/*
start at $s when $s[self::title]
return <book>{$w}</book>
未测试。