2009-06-26 79 views
3

我將如何轉換以下使用XSLTXSLT轉換與數

<blogger> 
    <post> 
    <text>...</text> 
    <categories>Engineering, Internet, Sausages</catgories> 
    </post> 
    <post> 
    <text>...</text> 
    <categories>Internet, Sausages</catgories> 
    </post> 
    <post> 
    <text>...</text> 
    <categories>Sausages</catgories> 
    </post> 
</blogger> 

Sausages (3) 
    Internet (2) 
    Engineering (1) 
+0

告訴我們你的企圖..... – 2009-06-26 03:53:52

+0

我嘗試過,並失敗了。 – Skiltz 2009-06-26 04:02:45

+0

你爲什麼不發佈有效的XML?我的意思是...這是一個剪切和粘貼的問題... – Tomalak 2009-06-26 08:56:48

回答

2

首先,改變你的XML

創建data.xml中

<blogger> 
<post> 
    <text>...</text> 
    <categories> 
     <category>Engineering</category> 
     <category>Internet</category> 
     <category>Sausages</category> 
    </categories>   
</post> 
<post> 
    <text>...</text> 
     <categories> 
     <category>Internet</category> 
     <category>Sausages</category> 
     </categories>  
    </post> 
<post> 
    <text>...</text> 
    <categories> 
     <category>Sausages</category> 
    </categories> 
</post> 
</blogger> 

然後再編寫XSLT,創建transform.xslt

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

<xsl:template match="/"> 

    <xsl:for-each select="//category"> 
    <xsl:variable name="value" select="."/> 
    <xsl:if test="count(preceding::category[.=$value]) = 0"> 
    <xsl:value-of select="."/> 
    <xsl:text> (</xsl:text> 
    <xsl:value-of select="count(//category[.=$value])"/>  
    <xsl:text>)</xsl:text><br/> 
    </xsl:if> 
</xsl:for-each> 

</xsl:template> 
</xsl:stylesheet> 

然後你就可以在Internet Explorer中打開data.xml中,並得到以下結果:

Engineering (1)Internet (2)Sausages (3)
2

你需要的是這樣的:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 

    <xsl:template match="/"> 
    <items> 
     <xsl:apply-templates select="/blogger/post/categories" /> 
    </items> 
    </xsl:template> 

    <xsl:template match="categories"> 
    <xsl:call-template name="split"> 
     <xsl:with-param name="pString" select="." /> 
    </xsl:call-template> 
    </xsl:template> 

    <!-- this splits a comma-delimited string into a series of <item>s --> 
    <xsl:template name="split"> 
    <xsl:param name="pString" select="''" /> 

    <xsl:variable name="vList" select=" 
     concat($pString, ',') 
    " /> 
    <xsl:variable name="vHead" select=" 
     normalize-space(substring-before($vList ,',')) 
    " /> 
    <xsl:variable name="vTail" select=" 
     normalize-space(substring-after($vList ,',')) 
    " /> 

    <xsl:if test="not($vHead = '')"> 
     <item> 
     <xsl:value-of select="$vHead" /> 
     </item> 
     <xsl:call-template name="split"> 
     <xsl:with-param name="pString" select="$vTail" /> 
     </xsl:call-template> 
    </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 

將會產生這個中間結果:

<items> 
    <item>Engineering</item> 
    <item>Internet</item> 
    <item>Sausages</item> 
    <item>Internet</item> 
    <item>Sausages</item> 
    <item>Sausages</item> 
</items> 

這:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 

    <xsl:output method="text" /> 
    <xsl:key name="kItem" match="item" use="." /> 

    <xsl:template match="/items"> 
    <xsl:apply-templates select="item"> 
     <xsl:sort 
     select="count(key('kItem', .))" 
     data-type="number" 
     order="descending" 
     /> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="item"> 
    <xsl:if test=" 
     generate-id() = generate-id(key('kItem', .)[1]) 
    "> 
     <xsl:value-of select=" 
     concat(
      ., ' (', count(key('kItem', .)), ')&#10;' 
     ) 
     " /> 
    </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 

,輸出:

Sausages (3) 
Internet (2) 
Engineering (1) 
1

其實,這是可以做到並且也不困難。這將做你想做的事:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="fo msxsl"> 
    <xsl:output encoding="UTF-8" indent="yes" method="xml"/> 
    <xsl:variable name="Separator">,</xsl:variable> 
    <xsl:template match="/"> 
    <xsl:variable name="NodeList"> 
     <xsl:apply-templates select="//categories"/> 
    </xsl:variable> 
    <xsl:variable name="Nodes" select="msxsl:node-set($NodeList)"/> 
    <html> 
     <head> 
     <title>Simple list</title> 
     </head> 
     <body> 
     <xsl:for-each select="$Nodes/Value"> 
      <xsl:variable name="value" select="."/> 
      <xsl:if test="count(preceding::Value[.=$value]) = 0"> 
      <xsl:value-of select="."/> (<xsl:value-of select="count($Nodes/Value[.=$value])"/>)<br/> 
      </xsl:if> 
     </xsl:for-each> 
     </body> 
    </html> 
    </xsl:template> 
    <xsl:template match="categories" name="Whole"> 
    <xsl:call-template name="Substring"> 
     <xsl:with-param name="Value" select="normalize-space(.)"/> 
    </xsl:call-template> 
    </xsl:template> 
    <xsl:template name="Substring"> 
    <xsl:param name="Value"/> 
    <xsl:choose> 
     <xsl:when test="contains($Value, $Separator)"> 
     <xsl:variable name="Before" select="normalize-space(substring-before($Value, $Separator))"/> 
     <xsl:variable name="After" select="normalize-space(substring-after($Value, $Separator))"/> 
     <Value> 
      <xsl:value-of select="$Before"/> 
     </Value> 
     <xsl:call-template name="Substring"> 
      <xsl:with-param name="Value" select="$After"/> 
     </xsl:call-template> 
     </xsl:when> 
     <xsl:otherwise> 
     <Value> 
      <xsl:value-of select="$Value"/> 
     </Value> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

其實,這是一塊蛋糕。 :-)