использование position() в преобразовании XSLT

#xml #xslt-1.0 #xslt-2.0

#xml #xslt-1.0 #xslt-2.0

Вопрос:

Я пытаюсь преобразовать следующий XML

 <?xml version="1.0" encoding="UTF-8"?>

<catalog>
    <cd QualifyingCode="1">
        <title>title1</title>
        <artist>artist1</artist>
    </cd>
    <cd QualifyingCode="1">
        <title>title2</title>
        <artist>artist2</artist>
    </cd>
    <cd QualifyingCode="2">
        <title>title3</title>
        <artist>artist3</artist>
    </cd>
    <cd QualifyingCode="2">
        <title>title4</title>
        <artist>artist4</artist>
    </cd>
</catalog>
  

Использование floowing XSLT

 <?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
  <body>
  <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th style="text-align:left">Title</th>
        <th style="text-align:left">Artist</th>
        <th style="text-align:left">ID</th>
      </tr>
      <xsl:for-each select="catalog/cd">
      <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="artist"/></td>
        <td><xsl:value-of select="position()"/></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>
  

Я получаю позицию как 1,2,3,4, используя position (). Я хочу, чтобы вывод для position () был 1,2,1,2 на основе атрибута «QualifyingCode».

итак, мой текущий результат :

 My CD Collection
Title   Artist  ID
title1  artist1 1
title2  artist2 2
title3  artist3 3
title4  artist4 4
  

и мой ожидаемый результат

  My CD Collection
    Title   Artist  ID
    title1  artist1 1
    title2  artist2 2
    title3  artist3 1
    title4  artist4 2
  

Ответ №1:

Одним из способов является использование

    <td><xsl:value-of select="count(preceding-sibling::cd[@QualifyingCode = current()/@QualifyingCode])   1"/></td>
  

Комментарии:

1. будет ли это работать, если код уточнения не имеет приращения 1? допустим, у меня есть код уточнения как «25» и «8»

2. Выражение count(preceding-sibling::cd[@QualifyingCode = current()/@QualifyingCode]) подсчитывает количество предшествующих родственных cd элементов, которые имеют то же QualifyingCode значение атрибута, что и контекстный узел (который является cd элементом, обработанным for-each или сопоставленным шаблоном). Итак, да, предполагая, что вы хотите посчитать элементы, имеющие одинаковое значение, это работает.

Ответ №2:

Я хочу, чтобы вывод для position () был 1,2,1,2 на основе атрибута «QualifyingCode».

Это недостаточно четкое требование, и пример тоже неоднозначен. Предполагая, что вы хотите, чтобы нумерация перезапускалась всякий раз, когда изменяется атрибут QualifyingCode, вам следует использовать xsl:number :

 <xsl:number from="cd[@QualifyingCode!=preceding-sibling::cd[1]/@QualifyingCode]" level="any" />
  

Обратите внимание, что это не то же самое, что подсчет предыдущих родственных файлов с тем же квалификационным кодом; разница станет очевидной, если вы добавите другой компакт-диск с @QualifyingCode= 1 к вашему текущему списку.

Ответ №3:

Я внес два изменения в ваш xslt: первое заключается в том, что обычно лучше использовать шаблон, а не для каждого. Другой конкретно отвечает на ваш вопрос, подсчитывая братьев и сестер, которые имеют одинаковый QualifyingCode :

 <?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
  <body>
  <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th style="text-align:left">Title</th>
        <th style="text-align:left">Artist</th>
        <th style="text-align:left">ID</th>
      </tr>
      <xsl:apply-templates select="catalog/cd"/>
    </table>
  </body>
  </html>
</xsl:template>

<xsl:template match="cd">
      <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="artist"/></td>
        <td><xsl:value-of select="count(preceding-sibling::cd[@QualifyingCode = 
             current()/@QualifyingCode])   1"/></td>
      </tr>
</xsl:template>

</xsl:stylesheet>
  

Комментарии:

1. Ах, я вижу, что я слишком медленно редактировал этот ответ. Надеюсь, что это в любом случае полезно.