Как мне применить шаблоны к каждому выбранному узлу в for-each?
-
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
таким образом, вам нужно будет изменить любую из следующих двух вещей в вашем подходе:
- Добавить
name="track"
атрибут дляmatch="track"
шаблон, а затем используйте<xsl:call-template/>
изнутриfor-each
(моя идея, и хуже, чемTim C
's) - Использование
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.Следовательно, ваш шаблон, который соответствует "дорожке", никогда не попадает в хит.