2008-12-03 135 views
10

如何保存發生在xsl:for-each中的迭代? (XSL中的變量是不可變的)xsl:for-each循環計數器

我的目標是找到特定級別上任何節點的最大子節點數。

例如,我可能要打印沒有在本次調查的任何問題超過2個響應節點:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<?xml-stylesheet type="text/xsl" href="testing.xsl"?> 
<Survey> 
    <Question> 
    <Response text="Website" /> 
    <Response text="Print Ad" /> 
    </Question> 
    <Question> 
    <Response text="Yes" /> 
    </Question> 
</Survey> 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:template match="/"> 
    <html> 
    <head> 
    </head> 
    <body> 
    <xsl:for-each select="Survey"> 
     The survey has <xsl:value-of select="count(child::Question)"/> questions. 
     <br /> 
     <xsl:variable name="counter">0</xsl:variable> 
     <xsl:for-each select="Question"> 
     <!-- TODO: increment the counter ??????? --> 
     </xsl:for-each> 
     No more than <xsl:value-of select="$counter"/> responses were returned for any question. 
    </xsl:for-each> 
    </body> 
    </html> 
</xsl:template> 
</xsl:stylesheet> 

回答

10

一個不「救都發生在一個xsl的迭代: for-each「,因爲XSLT is a functional language和變量是不可變的。

下列轉換查找想要的最大:

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

    <xsl:template match="/"> 
     <xsl:call-template name="maximum"> 
     <xsl:with-param name="pNodes" select="*/Question"/> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="maximum"> 
     <xsl:param name="pNodes"/> 

     <xsl:variable name="vNumNodes" select="count($pNodes)"/> 

     <xsl:choose> 
     <xsl:when test="$vNumNodes = 1"> 
      <xsl:value-of select="count($pNodes[1]/Response)"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:variable name="vHalf" 
       select="floor($vNumNodes div 2)"/> 

      <xsl:variable name="vMax1"> 
      <xsl:call-template name="maximum"> 
      <xsl:with-param name="pNodes" 
       select="$pNodes[not(position() > $vHalf)]"/> 
      </xsl:call-template> 
      </xsl:variable> 

      <xsl:variable name="vMax2"> 
      <xsl:call-template name="maximum"> 
      <xsl:with-param name="pNodes" 
       select="$pNodes[position() > $vHalf]"/> 
      </xsl:call-template> 
      </xsl:variable> 

      <xsl:value-of select= 
      "$vMax1*($vMax1 >= $vMax2) + $vMax2*($vMax2 > $vMax1)"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔應用:

 
<Survey> 
    <Question> 
     <Response text="Website" /> 
     <Response text="Print Ad" /> 
    </Question> 
    <Question> 
     <Response text="Yes" /> 
    </Question> 
</Survey> 

通緝產生結果:

請注意以下幾點命名爲maximum」模板遞歸調用自己並實現DVC (Divide and Conquer principle)的遞歸棧深度減少。節點列表被分成兩部分,兩個列表的最大值被計算(遞歸),並返回兩者中較大的一部分。