首页 > 解决方案 > 使用 XQuery 展平 XML

问题描述

我正在尝试将 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 很陌生,可能犯了一个愚蠢的错误。

标签: functionxquery

解决方案


<book>您的 XQuery 处理器将元素之间的边界空白<title>视为文本节点。要在查询中丢弃这些,您需要修改 typeswitch 中的元素大小写,如下所示:

case text() return
    if (normalize-space($node) eq "") then 
        ()
    else 
        element {string-join(fn:reverse($prefix), '-')} {string($node)}

推荐阅读