【问题标题】:Looping and recursion based on parameter passed基于传递的参数的循环和递归
【发布时间】:2010-05-18 10:45:48
【问题描述】:

我有一个如下组织的 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 中执行此操作 感谢您的帮助。

【问题讨论】:

  • 您能否进一步扩展您的约束条件?我推断您想为每个选定的孩子输出一个嵌套结构,其中包括该孩子的所有祖先。你会想省略一代吗?您是否会遇到为给定父母选择两个或更多后代的情况?如果是这样,您是要输出多个嵌套结构(每个选定的子节点一个),还是一个具有多个后代叶节点的结构?

标签: xslt


【解决方案1】:

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

<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>

【讨论】:

  • 感谢您的解决方案。XML 之上是- Bob Graham
    section>
    如何在您提供的表达式中包含 标记内的信息?
  • 我不明白这个问题。
  • 在原始 XML 中,我还需要显示标题信息。我之前给出的 XML 现在看起来像 - Bob Graham
    为了清楚起见,请在记事本中粘贴上面的 XML。我的查询是如何使用您提供的 XSLT 在最终输出 XML 中显示名字、车辆数据?
  • 您好 Jan,如果您理解我的问题,请告诉我?
  • 使用 XSLT,documentinfo + 子节点被复制到输出 XML。这和你问的有什么不同?
【解决方案2】:

这是 Jan Willem B 方法的替代方法。我不主张它更好或更坏。我提出它有两个原因:

  1. 您可能想看看递归方法是什么样子的

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

对于我的样式表,您将传递一个过滤器,仅列出您想要的叶节点。它会找到祖先。我为此假设您的根节点称为

<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>

【讨论】:

    猜你喜欢
    • 2023-02-22
    • 2019-11-11
    • 1970-01-01
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-27
    • 2017-01-21
    相关资源
    最近更新 更多