Цикл и рекурсия на основе переданного параметра - PullRequest
1 голос
/ 18 мая 2010

У меня есть 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 ]

2 голосов
/ 18 мая 2010

Рекурсия не обязательно является решением. В основном ваша строка с разделителями-запятыми может быть применена в качестве фильтра:

<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>
0 голосов
/ 19 мая 2010

Вот альтернатива подходу Яна Виллема Б. Я не утверждаю, что это лучше или хуже. Я представляю это по двум причинам:

  1. Возможно, вы захотите посмотреть, как будет выглядеть рекурсивный подход

  2. Он ведет себя по-разному для некоторых входных данных (хотя он ведет себя одинаково для данных вашего примера). В частности, если ваш фильтр включает в себя два узла, которые являются потомками одного и того же узла, эта таблица стилей выведет две вложенные структуры данных, каждая с одним конечным узлом, а ответ Яна Виллема 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...