Как мне применить шаблоны к каждому выбранному узлу в for-each?

StackOverflow https://stackoverflow.com/questions/1620527

  •  06-07-2019
  •  | 
  •  

Вопрос

Я знаю, что здесь я чего-то не понимаю.В приведенном ниже преобразовании XSLT фактический результат не соответствует желаемому результату.

Внутри for-each, я хочу применить match="track" шаблон для каждого выбранного track элемент.Если я правильно понял XSLT, при текущей настройке доступны только дочерние узлы каждого выбранного track элементы сопоставляются с шаблонами, а не с track сами элементы.

Как я могу сделать так, чтобы track элементы проходят через шаблон по желанию?Нужно ли мне переосмыслить весь свой подход?

Примечание:Преобразование выполняется с помощью PHP.XML-объявления были опущены для краткости.

XML-документ:

<album>
    <title>Grave Dancers Union</title>
    <track id="shove">Somebody To Shove</track>
    <track id="gold">Black Gold</track>
    <track id="train">Runaway Train</track>
    <producer>Michael Beinhorn</producer>
</album>

Таблица стилей XSL:

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/album">
        <ol>
            <xsl:for-each select="track">
                <li><xsl:apply-templates/></li>
            </xsl:for-each>
        </ol>
    </xsl:template>

    <xsl:template match="track">
        <a href="{@id}"><xsl:apply-templates/></a>
    </xsl:template>
</xsl:stylesheet>

Результат:

<ol>
    <li>Somebody To Shove</li>
    <li>Black Gold</li>
    <li>Runaway Train</li>
</ol>

Желаемый результат:

<ol>
    <li><a href="shove">Somebody To Shove</a></li>
    <li><a href="gold">Black Gold</a></li>
    <li><a href="train">Runaway Train</a></li>
</ol>
Это было полезно?

Решение

Я бы согласился с 'ndim' в том, что вам, вероятно, следует реструктурировать свой XSLT, чтобы избавиться от цикла xsl:for-each.

В качестве альтернативы, вы могли бы изменить xsl:apply-templates, чтобы выбрать текущий узел дорожки в xsl:for-each

<xsl:for-each select="track">
   <li>
      <xsl:apply-templates select="." />
   </li>
</xsl:for-each>

Сохранение xsl:for-each, по крайней мере, позволило бы вам сортировать треки в другом порядке, если это необходимо.

Другие советы

Я бы немного реструктурировал его (если вам не нужна сортировка for-each подход делает возможным):

<xsl:template match="/album">
  <ol>
    <xsl:apply-templates select="track"/>
  </ol>
</xsl:template>

<xsl:template match="track">
  <li><a href="{@id}"><xsl:apply-templates/></a></li>
<xsl:template>

Это выглядит короче и более по существу, ИМХО.

Я предполагаю, что ваш

    <xsl:for-each select="track">
       <li><xsl:apply-templates/></li>
    </xsl:for-each>

просматривает все элементы трека с помощью for-each, а затем применяет правила по умолчанию к своим потомкам.Таким образом, содержание for-each имеет тот же контекстный узел, что и match="track" шаблон имеет, и, таким образом, match="track" шаблон никогда не совпадает.

Если вы действительно хотите использовать for-each таким образом, вам нужно будет изменить любую из следующих двух вещей в вашем подходе:

  1. Добавить name="track" атрибут для match="track" шаблон, а затем используйте <xsl:call-template/> изнутри for-each (моя идея, и хуже, чем Tim C's)
  2. Использование Tim Cрешение с использованием <xsl:apply-templates select="."/>.Преимущество этого заключается в том, что избегается присвоение имен и сохраняется возможность сортировки дорожек.

Я думаю, что использование apply-templates и режимов шаблонов является более чистым решением:

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

  <xsl:template match="/">
    <body>
      <xsl:apply-templates select="album" mode="ol" />
    </body>
  </xsl:template>

  <xsl:template match="album" mode="ol">
    <ol>
      <xsl:apply-templates select="track" mode="li" />
    </ol>
  </xsl:template>

  <xsl:template match="track" mode="li">
    <li>
      <xsl:apply-templates select="." />
    </li>
  </xsl:template>

  <xsl:template match="track">
    <a href="{@id}">
      <xsl:value-of select="." />
    </a>
  </xsl:template>


</xsl:stylesheet>

приводит к:

<body>
  <ol>
    <li>
      <a href="shove">Somebody To Shove</a>
    </li>
    <li>
      <a href="gold">Black Gold</a>
    </li>
    <li>
      <a href="train">Runaway Train</a>
    </li>
  </ol>
</body>

Оператор for-each изменяет контекстный узел с альбома на дорожку.Вызов apply-templates по умолчанию применяет шаблоны к дочерним узлам контекстного узла, которые в вашем случае являются дочерними узлами элемента track.Следовательно, ваш шаблон, который соответствует "дорожке", никогда не попадает в хит.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top