2009-10-25 6 views
6

Я знаю, что мне что-то не хватает. В приведенном ниже преобразовании 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 Stylesheet:

<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> 

ответ

9

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

В качестве альтернативы, вы можете изменить XSL: применить-шаблоны для выбора текущего узла дорожки в пределах XSL: для-каждого

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

Сохраняя XSL: за-каждый будет, по крайней мере, позволит вам сортируйте треки в другом порядке, если хотите.

+0

Хорошая уловка при сортировке. Я думаю, это лучшее решение из-за сортировки. – ndim

+0

Я мог бы поклясться, что я уже пробовал это, но, думаю, нет. Это именно то, что я искал! – Jakob

4

я реструктурировать это немного (если не нужен сортировки 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)
  2. Использование решения Tim C с использованием <xsl:apply-templates select="."/>. Преимущество этого заключается в том, чтобы избежать именования и сохранения возможности сортировки дорожек.
+0

Решение для реструктуризации кажется менее модульным, чем я хотел бы (он не позволяет включать дорожки в '

' или '' где-то еще на странице/сайте, по крайней мере, не используя одну и ту же таблицу стилей) но вы, вероятно, правы в том, что это самое гладкое решение для этого примера. – Jakob

+0

@Jakob Я знаю, что это древний, но я просто хочу указать, что вы можете использовать атрибут mode, чтобы выбрать другой шаблон для тех же узлов. Подобно '' и ' ...'. – janek37

0

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

<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> 
0

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

Смежные вопросы