基于参数传递的循环和递归

时间:2010-05-18 10:45:49

标签: xslt

我的XML组织如下 -

  

<section name="Parent 1 Text here" ID="1" >
  <section name="Child 1 Text here" ID="11">
  </section>
  <section name="Child 2 Text here" ID="12">
    <section name="GrandChild Text here"  ID="121" >
    </section>
  </section>
</section>

<section name="Parent 2 Text here" ID="2" >
  <section name="Child 1 Text here" ID="22">
  </section>
  <section name="Child 2 Text here" ID="23">
    <section name="GrandChild Text here"  ID="232" >
    </section>
  </section>
</section>         

 

我必须生成以下输出XML -

   

<section name="Parent 1 Text here" ID="1" >
  <section name="Child 2 Text here" ID="12">
    <section name="GrandChild Text here"  ID="121" >
    </section>
  </section>
</section>

<section name="Parent 2 Text here" ID="2" >
  <section name="Child 2 Text here" ID="23">
  </section>
</section>

我必须在上面使用XSLT 1.0转换。我打算将逗号分隔的字符串作为参数传递,其值为“1,12,121,2,23”

我的问题 - 如何在XSLT 1.0中循环逗号分隔参数? 是否有更简单的方法来实现上述目标。请记住我必须在XSLT 1.0中执行此操作 感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

递归不一定是解决方案。基本上你的逗号分隔字符串可以用作过滤器:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:param name="filter">1,12,121,2,23</xsl:param>

  <xsl:template match="section">
    <xsl:if test="contains(concat(',', $filter, ','), concat(',', @ID, ','))">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>

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

</xsl:stylesheet>

答案 1 :(得分:0)

这是Jan Willem B的方法的替代方案。我并不认为它好或坏。我提出这个有两个原因:

  1. 您可能希望看到递归方法的样子

  2. 对于某些输入数据,它的行为有所不同(尽管它对您的示例数据的行为相同)。具体来说,如果您的过滤器包含两个节点,这两个节点都是同一节点的后代,则此样式表将输出两个嵌套数据结构,每个结构都有一个叶节点,而Jan Willem B的答案输出一个具有两个叶节点的嵌套结构。不知道你想要哪一个。

  3. 对于我的样式表,您将传递一个过滤器,仅列出您想要的叶节点。它会找到祖先。我假设您的根节点名为&lt; doc&gt;

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml"/>
    
        <xsl:param name="descendant-ids" select="'121,23'"/>
    
        <xsl:template match="/">
            <doc>
                <xsl:call-template name="recurse-ids">
                    <xsl:with-param name="ids" select="concat($descendant-ids,',')"/>
                </xsl:call-template>
            </doc>
        </xsl:template>
    
        <xsl:template name="recurse-ids">
            <xsl:param name="ids"/>
            <xsl:variable name="id" select="substring-before($ids,',')"/>
            <xsl:variable name="remaining-ids" select="substring-after($ids,',')"/>
            <xsl:apply-templates select="/doc/section">
                <xsl:with-param name="id" select="$id"/>
            </xsl:apply-templates>
            <xsl:if test="$remaining-ids">
                <xsl:call-template name="recurse-ids">
                    <xsl:with-param name="ids" select="$remaining-ids"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:template>
    
        <xsl:template match="section">
            <xsl:param name="id"/>
            <xsl:if test="starts-with($id,@ID)">
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()">
                        <xsl:with-param name="id" select="$id"/>
                    </xsl:apply-templates>
                </xsl:copy>
            </xsl:if>
        </xsl:template>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>