2015-04-23 46 views
0

我习惯于在我的XSLT中具有基于输入中节点树的条件。但我想根据输出结果来做。有什么办法吗?基于输出树的XSLT条件

下面是一个例子。

输入:

<top> 
    <a> 
     <z> 
      <item> 
       <id>4</id> 
      </item> 
      <item> 
       <id>5</id> 
      </item> 
     </z> 
    </a> 
</top> 

希望的输出:

<thing> 
    <upper> 
     <a> 
      <z> 
       <item> 
        <id>upper-4</id> 
       </item> 
       <item> 
        <id>upper-5</id> 
       </item> 
      </z> 
     </a> 
    </upper> 
    <lower> 
     <a> 
      <z> 
       <item> 
        <id>lower-4</id> 
       </item> 
       <item> 
        <id>lower-5</id> 
       </item> 
      </z> 
     </a> 
    </lower> 
</thing> 

注意,树基本上由一个向下复制,唯一的变化是在id节点的值已被根据是否修改我们在upperlower树中。

我现在的XSLT:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

    <xsl:template match="top"> 
     <thing> 
      <upper> 
       <xsl:apply-templates /> 
      </upper> 
      <lower> 
       <xsl:apply-templates /> 
      </lower> 
     </thing> 
    </xsl:template> 

    <xsl:template match="id"> 
     <!-- I want to prepend this with "upper" or "lower" depending which block we're in --> 
     <xsl:value-of select="text()" /> 
    </xsl:template> 

    <!-- identity template --> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()" /> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

这是一个简单的例子,也有az之间的树很多节点,以及节点item可以出现在a下的不同深度。

最初我的状态看起来像ancestor::upper,但显然不起作用,因为upper在输出中,而不是输入。

我也考虑过试图传递一个参数来说,如果我们在upperlower,但这意味着更新每一个模板(包括身份模板)有一个参数,也传递给它它调用的任何模板。如果可能,我真的想避免这种情况。

所以,如果有一种方法可以将变量传递给被调用的模板而不必声明变量,那就行了。或者,如果我可以编写一个条件来查看调用我们的模板或者我们上面树中的输出,那就行得通了。或者还有其他方法可以做到这一点吗?

请注意,我使用的是撒克逊处理器,所以我可以使用特定的功能(例如,如果有帮助,我可以致电给某些java)。

谢谢。

+0

您的代码说'版本= “2.0”'但Xalan的是一个XSLT 1.0处理器。如果您切换到Saxon 9并真正使用XSLT 2.0,那么您可以使用隧道参数来避免必须使用每个apply-templates传递参数。除此之外,我认为参数是正确的方法。 –

+0

@MartinHonnen对不起,我的意思是撒克逊...(我目前使用的是版本9.1.0.8)我会研究隧道参数,但我之前没有遇到过。 – stripybadger

回答

0

下面是使用的隧道参数与XSLT 2.0的溶液:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs"> 

    <!-- identity template --> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="top"> 
     <thing> 
      <upper> 
       <xsl:apply-templates> 
        <xsl:with-param name="tree-id" tunnel="yes" select="'upper-'"/> 
       </xsl:apply-templates> 
      </upper> 
      <lower> 
       <xsl:apply-templates> 
        <xsl:with-param name="tree-id" tunnel="yes" select="'lower-'"/> 
       </xsl:apply-templates> 
      </lower> 
     </thing> 
    </xsl:template> 

    <xsl:template match="id"> 
     <xsl:param name="tree-id" tunnel="yes"/> 
     <xsl:copy> 
      <!-- I want to prepend this with "upper" or "lower" depending which block we're in --> 
      <xsl:value-of select="concat($tree-id, .)" /> 
     </xsl:copy> 
    </xsl:template> 


</xsl:stylesheet> 
+0

完美 - 我之前没有遇到隧道参数,谢谢。 – stripybadger