如何使用XQuery计算XML文件中所有元素和属性的出现次数?

时间:2017-09-14 21:39:00

标签: xml xquery

输入文件:

<?xml version="1.0" encoding="UTF-8"?> 
    <books>
        <book id="6636551">
            <master_information>
                <book_xref>
                    <xref type="Fiction" type_id="1">72771KAM3</xref>
                    <xref type="Non_Fiction" type_id="2">US72771KAM36</xref>
                </book_xref>
            </master_information>
            <book_details>
                <price>24.95</price>
                <publish_date>2000-10-01</publish_date>
                <description>An in-depth look at creating applications with XML.</description>
            </book_details>
        </book>
        <book id="119818569">
            <master_information>
                <book_xref>
                    <xref type="Fiction" type_id="1">070185UL5</xref>
                    <xref type="Non_Fiction" type_id="2">US070185UL50</xref>
                </book_xref>
            </master_information>
            <book_details>
                <price>19.25</price>
                <publish_date>2002-11-01</publish_date>
                <description>A former architect battles corporate zombies, an evil sorceress, and her own childhood to become queen of the world.</description>
            </book_details>
        </book>
        <book id="119818568">
            <master_information>
                <book_xref>
                    <xref type="Fiction" type_id="1">070185UK7</xref>
                    <xref type="Non_Fiction" type_id="2">US070185UK77</xref>
                </book_xref>
            </master_information>
            <book_details>
                <price>5.95</price>
                <publish_date>2004-05-01</publish_date>
                <description>After the collapse of a nanotechnology society in England, the young survivors lay the foundation for a new society.</description>
            </book_details>
        </book>
        <book id="119818567">
            <master_information>
                <book_xref>
                    <xref type="Fiction" type_id="1">070185UJ0</xref>
                    <xref type="Non_Fiction" type_id="2">US070185UJ05</xref>
                </book_xref>
            </master_information>
            <book_details>
                <price>4.95</price>
                <publish_date>2000-09-02</publish_date>
                <description>When Carla meets Paul at an ornithology conference, tempers fly as feathers get ruffled.</description>
            </book_details>
        </book>
    </books>

我能够用标题创建一个简单的计数函数(仅供参考 - 我是Xquery的新手)

let $x := string-join(('xref', count(//book//xref)), '&#58;')
return $x

我按照预期使用标题计数

xref:8

我尝试扩展它以适用于所有元素和属性,但它不起作用。我在$ x中添加了明显错误的标题 - 是否有一个函数来获取我可以使用的元素/ attr的名称。我找不到一个。

for $x in //book
let $c := string-join(($x, count($x)), '&#58;')
return $x

我希望前缀标题是“元素/ attr的名称”,然后是冒号和该元素/ attr的计数。我究竟做错了什么?我非常感谢你的回复。

P.S。我知道有些人可能认为这种东西在XSLT中更容易做,但我想尽可能地坚持使用Xquery进行所有数据查询。我发现Xquery比XSLT更容易理解,因为它的SQL语法结构我已经习惯了。

2 个答案:

答案 0 :(得分:4)

这在XQuery中也很容易做到。策略是首先获取元素名称的不同值,然后查询它们的计数。棘手的部分是在保留名称空间的同时这样做。下面是一个示例,首先将元素QName值构建为Clark表示法字符串,然后获取不同的值,然后在通过XPath查询之前重建QName。

let $doc := (: some document :)
let $names := distinct-values($doc//*/concat('{' , namespace-uri-from-QName(node-name(.)), '}', local-name(.)))
for $n in $names
let $ns := substring-after(substring-before($n, '}'), '{')
let $local-name := substring-after($n, '}')
let $qname := QName($ns, $local-name)
return concat($n, ':', count($doc//*[node-name(.) = $qname]))

可以轻松修改此查询以报告多个文档或元素,但请注意,随着元素数量的增加,运行查询所需的时间也会增加。

答案 1 :(得分:2)

以下是来自@wst的解决方案的变体,适用于利用XQuery 3.0功能:

"{}b:2"
"{c.com}c:1"
"{}a:1"

输出(取决于序列化方法,并以未定义的顺序):

datasets