2009-09-30 38 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>