2009-09-30 61 views
2

我需要编写一个通用的xsl文件,这个xsl文件会接受一个xml文档并输出节点数量和名称。所以,如果我有一个像下面这样的文件:节点数量和发生率 - XSL

<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> 

回答

4

你想使用的计数功能:

<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)" /> 
4

通用解决方案

<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> 

说明::用于与任何名称包含输入节点可使用Muenchian方法来进行使用xsl:key,创建从名称到具有该名称的节点的映射。然后遍历所有唯一的名称,并输出名称的节点数。这里的主要技巧是如何遍历唯一的名称。请参阅链接页面,了解用于确定foo是否仅包含上下文节点的节点集的count(.|foo)=1成语的解释。

+0

+1,虽然我很喜欢'产生-ID()'更好。这个问题看起来有点像我的功课。 – Tomalak 2009-10-01 09:34:44

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>