我需要编写通用xsl,它将接收xml文档并输出节点数及其名称。所以,如果我有一个如下文件:
<assets>
<asset>
<type>hardware</type>
<item>
<name>HP laptop</name>
<value>799</value>
</item>
<item>
<name>server</name>
<value>1000</value>
</item>
<item>
<name>ViewSonic Monitor</name>
<value>399</value>
</item>
</asset>
<asset>
<type>software</type>
<item>
<name>Windows Vista</name>
<value>399</value>
</item>
<item>
<name>Office XP</name>
<value>499</value>
</item>
<item>
<name>Windows 7</name>
<value>399</value>
</item>
<item>
<name>MS Project Professional 2007</name>
<value>299</value>
</item>
</asset>
</assets>
输出结果为:
<output>
<node name="assets" count="1"/>
<node name="asset" count="2"/>
<node name= "type" count="??"/>
<node name="item" count=??/>
<node name="name" count=??/>
<node name="value" count=??/>
</output>
答案 0 :(得分:6)
您需要使用计数功能:
<xsl:value-of select="count(assets/asset)" />
所以你的代码看起来像是:
Assets: <xsl:value-of select="count(assets)" />
Asset: <xsl:value-of select="count(assets/asset)" />
Item: <xsl:value-of select="count(assets/asset/item)" />
答案 1 :(得分:4)
包含具有任何名称的节点的输入的通用解决方案可以使用Muenchian方法完成:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="nodes-by-name" match="*" use="name()"/>
<xsl:template match="/">
<output>
<xsl:for-each select="//*[count(.|key('nodes-by-name', name())[1]) = 1]">
<node name="{name()}" count="{count(key('nodes-by-name', name()))}"/>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
说明:使用xsl:key
,创建从名称到具有该名称的节点的映射。然后遍历所有唯一名称,并输出名称的节点计数。这里的主要技巧是如何遍历唯一的名称。有关用于确定count(.|foo)=1
是否仅包含上下文节点的节点集的foo
惯用语的解释,请参阅链接页面。
答案 2 :(得分:1)
这是我使用XSLT 2.0的解决方案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:element name="output">
<xsl:for-each-group select="//*" group-by="name()">
<xsl:element name="node">
<xsl:attribute name="name">
<xsl:value-of select="current-grouping-key()"/>
</xsl:attribute>
<xsl:attribute name="count">
<xsl:value-of select="count(current-group())"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each-group>
</xsl:element>
</xsl:template>
</xsl:stylesheet>