XSLT xsl: для каждого условного выбора - PullRequest
6 голосов
/ 15 июня 2011

У меня есть кусок XML, который выглядит следующим образом:

<root>
  <tag1>tractor</tag1>
  <tag2>
    <subtag1 att="apple" />
    <subtag2>
      <subsubtag1>red</subsubtag1>        
      <subsubtag2>lunch</subsubtag2>
    </subtag2>
  </tag2>      
  <tag1>forklift</tag1>
  <tag2>
    <subtag1 att="pear" />
    <subtag2>
      <subsubtag1>green</subsubtag1>        
      <subsubtag2>breakfast</subsubtag2>
    </subtag2>
  </tag2>      
  <tag2>
    <subtag1 att="apple" />
    <subtag2>
      <subsubtag1>green</subsubtag1>        
      <subsubtag2>dinner</subsubtag2>
    </subtag2>
  </tag2>   
  <tag1>combine harvester</tag1>
</root>

Что мне нужно, чтобы преобразовать его так, чтобы я получал подтеги 2 и 3 от каждого узла tag2, но только от узлов tag2, где subtag1 - это яблоко. Мне также нужен порядковый номер для каждого.

Мой текущий код выглядит примерно так:

<xsl:for-each select="//tag2">
  <apple>
    <seq_num><xsl:value-of select="position()" /></seq_num>
    <colour><xsl:value_of select="subtag2" /></colour>  
    <meal><xsl:value_of select="subtag3" /></meal>  
  </apple>
</xsl:for-each>

Это было бы хорошо, за исключением того, что мне нужно, чтобы for-each только возвращал tag2, которые являются яблоками (то есть subtag1 = apple). Я не могу использовать xsl: if или xsl: when потому что тогда порядковый номер был бы неточным для второго яблока.

Есть идеи?

Спасибо, Rik

1 Ответ

13 голосов
/ 15 июня 2011

Чтобы остаться с вашим кодом, должно быть просто:

<xsl:for-each select="//tag2[subtag1/@att='apple']">
  <apple>
    <seq_num><xsl:value-of select="position()" /></seq_num>
    <colour><xsl:value-of select="subtag2/subsubtag1" /></colour>  
    <meal><xsl:value-of select="subtag2/subsubtag2" /></meal>  
  </apple>
</xsl:for-each>

В соответствии с комментариями ниже, как предлагается, лучше избегать //.Вы должны быть в состоянии, когда в правильном контексте.Например:

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

    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/root">
        <xsl:for-each select="tag2[subtag1/@att='apple']">
            <apple>
                <seq_num><xsl:value-of select="position()" /></seq_num>
                <colour><xsl:value-of select="subtag2/subsubtag1" /></colour>  
                <meal><xsl:value-of select="subtag2/subsubtag2" /></meal>  
            </apple>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

При использовании на вашем входе выдает тот же результат.Или еще лучше, избегайте также xsl:for-each:

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

    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/root">
        <xsl:apply-templates select="tag2[subtag1/@att='apple']"/>
    </xsl:template>

    <xsl:template match="tag2">
        <apple>
            <seq_num><xsl:value-of select="position()" /></seq_num>
            <colour><xsl:value-of select="subtag2/subsubtag1" /></colour>  
            <meal><xsl:value-of select="subtag2/subsubtag2" /></meal>  
        </apple>
    </xsl:template>

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