2012-07-31 70 views
1

下面的XML文檔表示3號,2,2和2,一種節點<s>被計數爲一個數字,並用<zero/>結束。XSLT遞歸乘法

<?xml version="1.0" encoding="UTF-8"?> 
    <nat xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="nat.xsd"> 
     <s> 
     <s> 
      <zero/> 
     </s> 
     </s> 
     <s> 
     <s> 
      <zero/> 
     </s> 
     </s> 
     <s> 
     <s> 
      <zero/> 
     </s> 
     </s> 
    </nat> 

我剛開始學習xslt,這是遞歸練習之一。我可以遞歸地加上所有數字,但是這個乘以兩個以上的數字只是讓我大開眼界。我不知道該怎麼做。

以上XML文檔的預期的答案是787-8(忽略格式):

<s><s><s><s><s><s><s><s><zero/></s></s></s></s></s></s></s></s> 我的想法是這樣的,我可以有一個模板,加入做乘法兩個數。所以對於這個2x2x2,我會做第二次2次返回4的第三次2,最後做2 * 4。但是,不像java或scheme,call模板不會在xslt中返回值,所以我很欣賞任何提示/幫助。

更新: 我得到了我的答案,在打印模板中添加到Dimitre的答案。那就是:

<xsl:template name="print"> 
    <xsl:param name="pAccum"/> 
     <xsl:choose> 
      <xsl:when test="$pAccum > 0"> 
       <s> 
        <xsl:call-template name="print"> 
         <xsl:with-param name="pAccum" select="$pAccum - 1"/> 
        </xsl:call-template> 
       </s> 
      </xsl:when> 
      <xsl:otherwise> 
       <zero/> 
      </xsl:otherwise>  
     </xsl:choose> 
</xsl:template> 
+0

這似乎不是一個合適的鍛鍊遞歸 - - 爲什麼你不嘗試一個更簡單和更明確的問題?有:' > > >'並找到所有'num'元素的乘積。 – 2012-07-31 03:56:57

+1

您對模板的評論讓您聽起來好像您想在XSLT 1.0中執行此操作一樣。如果你真的需要使用已經取代近6年的語言版本,你應該在你的文章中這樣說。那麼對於我們這些對XSLT 1.0來說是一個遙遠的衰落內存的人來說,不需要麻煩回答。 – 2012-07-31 08:00:53

+0

@MichaelKay:哎喲,對於模糊評論我很抱歉。這是針對XSLT 2.0的。正如我在試圖解決這個問題時想的那樣大聲。 – bili 2012-07-31 12:58:37

回答

1

這種轉變

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:call-template name="product"> 
    <xsl:with-param name="pArgs" select="//zero"/> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="product"> 
    <xsl:param name="pAccum" select="1"/> 
    <xsl:param name="pArgs" select="/.."/> 

    <xsl:choose> 
    <xsl:when test="not($pArgs)"> 
    <xsl:value-of select="$pAccum"/> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:call-template name="product"> 
    <xsl:with-param name="pAccum" 
      select="$pAccum * count($pArgs[1]/ancestor::s)"/> 
    <xsl:with-param name="pArgs" select="$pArgs[position() > 1]"/> 
    </xsl:call-template> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<nat> 
    <s> 
     <s> 
      <zero/> 
     </s> 
    </s> 
    <s> 
     <s> 
      <zero/> 
     </s> 
    </s> 
    <s> 
     <s> 
      <zero/> 
     </s> 
    </s> 
</nat> 

產生想要的,正確的結果:

8 

說明

原始遞歸與停止條件 - 空的參數節點集合和蓄能器 - 參數用於使當前累加結果到下一個遞歸調用。

+0

+1正確的答案,但不是顯示8就應該顯示。有8 表示結束。 – bili 2012-07-31 14:44:00

+0

謝謝!它很好地工作。我通過調試器運行了解決方案,並添加到模板中以獲取答案的正確表示。看到我上面的編輯! – bili 2012-07-31 15:44:29

+0

@bili:不客氣。是的,我完全忽略了這種相當奇怪的格式。我不知道你想要一個XSLT 2.0解決方案 - 在這種情況下,使用'xsl:finction'更方便。另外,如果你對這個主題感興趣,你可能會發現它有趣的閱讀FXSL:http://conferences.idealliance.org/extreme/html/2006/Novatchev01/EML2006Novatchev01.html – 2012-07-31 16:02:06

1

在XSLT 2.0我會用一對函數開始:

<xsl:function name="f:toNumber" as="xs:integer"> 
    <xsl:param name="z" as="element(zero)"/> 
    <xsl:sequence select="count($z/ancestor::*)"/> 
</xsl:function> 

<xsl:function name="f:fromNumber" as="element()> 
    <xsl:param name="z" as="xs:integer"/> 
    <xsl:choose> 
    <xsl:when test="$z=0"><zero/></xsl:when> 
    <xsl:otherwise><s><xsl:sequence select="f:fromNumber($z - 1)"/> 
</xsl:function> 

剷球您的數字表示的怪事。

現在你只需要一個計算數字序列的產品功能:

<xsl:function name="f:product" as="xs:integer"> 
    <xsl:param name="in" as="xs:integer"/> 
    <xsl:sequence select="if (count($in) = 1) then $in[1] else $in * f:product($in[position()>1])"/> 
</xsl:function> 

,剩下的就是孩子們的遊戲...

+0

謝謝你的回答! – bili 2012-07-31 22:28:40