【发布时间】:2018-08-15 15:06:40
【问题描述】:
我正在尝试将 XML 层次结构展平到文本节点,其中输出标记名称是每个文本节点路径上的连字符连接标记。我将http://www.chilkatsoft.com/xml-samples/bookstore.xml 提供的示例 XML 用作输入。
到目前为止,我已经创建了这个 XQuery:
declare function local:flatten($prefix as xs:string*, $nodes as node()*) as node()*
{
for $node in $nodes
return
typeswitch($node)
case element() return
local:flatten(insert-before($prefix, 1, $node/name()), $node/node())
case text() return
element {string-join(fn:reverse($prefix), '-')} {string($node)}
default return
'oops'
};
for $b in //bookstore/book return
local:flatten((), $b)
这主要是有效的,但输出看起来像:
<?xml version="1.0" encoding="UTF-8"?>
<book>
</book>
<book-title>The Iliad and The Odyssey</book-title>
<book>
</book>
<book-price>12.95</book-price>
<book>
</book>
<book-comments>
</book-comments>
<book-comments-userComment> Best translation I've read. </book-comments-userComment>
<book-comments>
</book-comments>
<book-comments-userComment> I like other versions better. </book-comments-userComment>
<book-comments>
</book-comments>
<book>
</book>
...
我不关心此时是否缺少根元素(一次一步),但我不希望正确呈现的文本节点之间存在虚假的空父标签。我究竟做错了什么? 我对 XQuery 很陌生,可能犯了一个愚蠢的错误。
【问题讨论】:
-
检查您的数据。我针对您提供的文档示例运行了您的代码,并且没有返回空的书籍元素。
-
你不需要一个函数来展平和收集元素名称,你也可以使用
for $book in bookstore/book, $text in $book//text()[normalize-space()] return element { string-join(($text/ancestor-or-self::* except $book/ancestor::*)/name(), '-') } { data($text) },见xqueryfiddle.liberty-development.net/jyyiVhi -
@MartinHonnen 确实更整洁。