XSLT - рекурсивно работает вне - PullRequest
3 голосов
/ 11 февраля 2009

Я понимаю, как обработать этот документ (ниже) с помощью XSLT от самого внешнего элемента person до самого внутреннего. Но мне было интересно, если:

  1. Если возможно работать от самого глубокого элемента.
  2. Как это будет выглядеть в моем примере.
<?xml version="1.0" encoding="utf-8" ?>
<container>
  <person name="Larry">
    <person name="Moe">
      <person name="Curly">
        <person name="Shemp">

        </person>
      </person>
    </person>
  </person>
</container>

Ответы [ 3 ]

11 голосов
/ 11 февраля 2009

Вы можете использовать parent :: axis для работы.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
      <xsl:apply-templates select="//person[not(person)]"/>
    </xsl:template>
  <xsl:template match="person">
    <xsl:value-of select="@name"/> -&gt; <xsl:apply-templates select="parent::person"/>
  </xsl:template>
</xsl:stylesheet>

Не проверено, возможно, я не в синтаксисе.

На нем должно быть напечатано Shemp -> Curly -> Moe -> Larry

2 голосов
/ 12 февраля 2009

Вот наиболее общий способ выполнения «обратной рекурсии» , который не зависит от этой конкретной проблемы и может использоваться в самых разных задачах.

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="/">
      <xsl:call-template name="backwardsRecursion">
        <xsl:with-param name="pList" select="//person"/>
      </xsl:call-template>
    </xsl:template>

    <xsl:template name="backwardsRecursion">
      <xsl:param name="pList"/>

      <xsl:if test="$pList">
        <xsl:apply-templates select="$pList[last()]"/>

        <xsl:call-template name="backwardsRecursion">
          <xsl:with-param name="pList" select=
           "$pList[position() &lt; last()]"/>
        </xsl:call-template>
      </xsl:if>
    </xsl:template>

    <xsl:template match="person">
      <xsl:value-of select="concat(@name,'&#xA;')"/>
    </xsl:template>
</xsl:stylesheet>

при применении к первоначально предоставленному XML-документу дает желаемый результат :

Shemp
Curly
Moe
Larry

Обратите внимание , что вызывается универсальный шаблон с именем "backwardsRecursion", который действительно реализует обратную рекурсию. Этот шаблон не знает ничего об узлах, которые он обрабатывает, или о том, как они будут обрабатываться .

Таким образом, этот шаблон можно использовать в любой ситуации, когда требуется обратная рекурсивная обработка.

1 голос
/ 11 февраля 2009

Решение, похожее на решение teun, но позволяющее элементам person вступать в непосредственные отношения родитель-потомок , выглядит следующим образом:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="/">
      <xsl:apply-templates select="//person[not(person)]"/>
    </xsl:template>

    <xsl:template match="person" name="tPerson">
       <xsl:value-of select="concat(@name,'&#xA;')"/>

       <xsl:apply-templates select=
          "ancestor::person[1]"/>
    </xsl:template>
</xsl:stylesheet>

При применении к первоначально предоставленному XML-документу, получается правильный результат :

Shemp

завитые

Мо

Larry

Хорошо знать, что многие проблемы этого типа вообще не требуют рекурсии! Это преобразование дает точно такой же результат и включает только итерацию :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

    <xsl:template match="/">
       <xsl:for-each select="//person[not(person)]">
          <xsl:for-each select="ancestor::person | .">
            <xsl:sort select="position()" order="descending"/>
                <xsl:value-of select="concat(@name,'&#xA;')"/>
          </xsl:for-each>
       </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Обратите внимание на сортировку , обеспечивающую обратный порядок обработки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...