Родительская/дочерняя группа Xslt

У меня возникли проблемы с получением следующего результата преобразования xml/xslt:

<root>
  <node>   
    <id>1</id>
    <parentid></parentid>
    <name>file 1</name>
  <node>
  <node>   
    <id>2</id>
    <parentid></parentid>
    <name>file 2</name>
  <node>
  <node>   
    <id>3</id>
    <parentid>2</parentid>
    <name>file 3</name>
  <node>
  <node>   
    <id>4</id>
    <parentid></parentid>
    <name>file 4</name>
  <node>
  <node>   
    <id>5</id>
    <parentid>2</parentid>
    <name>file 5</name>
  <node>
</root>

я хотел бы, чтобы выходной html был примерно таким:

 <ul>
    <li>file 1</li>
    <li>file 2</li>
       <ul>
          <li>file 3</li>
          <li>file 5</li>
       </ul>
    <li>file 4</li>
 </ul>

person user732238    schedule 30.04.2011    source источник


Ответы (2)


Ключевым моментом (без каламбура) является использование <xsl:key> для установки отношений родитель-потомок. Как только это определено, остальное легко.

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:key name="getchildren" match="node" use="parentid"/>

    <xsl:template match="root">
        <ul>
            <xsl:apply-templates
              select="node[parentid[not(normalize-space())]]"/>
        </ul>
    </xsl:template>

    <xsl:template match="node">
        <li><xsl:value-of select="name"/></li>
        <xsl:variable name="children" select="key( 'getchildren', id )"/>
        <xsl:if test="$children">
            <ul><xsl:apply-templates select="$children"/></ul>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>
person Lumi    schedule 30.04.2011

person    schedule
comment
Использование <xsl:key> имеет преимущество в производительности, которое, конечно, не имеет никакого значения для небольших входных данных. По крайней мере, для меня он также имеет преимущество в ясности, будучи более декларативным, менее процедурным, но это может быть делом личного вкуса. - person Lumi; 30.04.2011
comment
Правда, ключ имеет лучшую производительность для больших входных данных, но для этого требуется понимание того, как работают ключи xsl, что не требуется для понимания основной работы этого преобразования. Op явно новичок в XSLT, поэтому я старался сделать его как можно более простым. Концептуально эти два решения в значительной степени идентичны, ни одно из них не является процедурным (использование for-each и call-template было бы процедурным). - person Lucero; 30.04.2011
comment
@Alejandro Алехандро, так как бы вы назвали стиль программирования style, когда явно используете конструкции с for-each и call-template? - person Lucero; 01.05.2011
comment
@Lucero: Ну, это зависит. Что касается стиля, существует классификация между стилями push и pull. Мне не нравятся шаблоны brick (правило корня документа выполняет все преобразования), но нет ничего концептуально неправильного в использовании инструкций xsl:for-each и xsl:call-template. - person ; 02.05.2011
comment
@Alejandro, В Википедии есть следующее определение декларативного программирования: декларативное программирование часто определяется как любой стиль программирования, который не является императивным. [...] Программа, которая описывает, какие вычисления должны быть выполнены, а не как их вычислять - и это именно моя точка зрения. Хотя XSLT является декларативным языком, вы все же можете использовать императивный стиль, используя конструкции, которые определяют что вместо как. - person Lucero; 02.05.2011
comment
Tnx, ребята, улучшили свои навыки работы с xslt, добавив немного больше знаний. - person user732238; 02.05.2011