Понимание соответствия `apply-templates` - PullRequest
5 голосов
/ 26 января 2010

Правильно ли я считаю, что объявление apply-templates должно соответствовать всем шаблонам, которые могут быть применены для выбора?

Например, учитывая следующий фрагмент xml:

<doc>
  <foo bar="1" baz="2">boz</foo>
</doc>

и следующая таблица стилей:

<xsl:template match="/">
  <xsl:apply-templates select="foo" mode="xyz" />
</xsl:template>

<xsl:template mode="xyz" match="foo[bar='1']">
  abc
</xsl:template>

<xsl:template mode="xyz" match="foo[baz='2']">
  def
</xsl:template>

Я ожидаю, что результат будет:

abc
def

Это правильно?

Ответы [ 3 ]

6 голосов
/ 26 января 2010

Нет, вы не получите оба выхода, так как будет выбран только один шаблон. См. на этой странице для правил разрешения конфликтов, если существует несколько возможных шаблонов.

После исправления таблицы стилей (аналогично тому, как это делал Рубенс, но с теми же режимами), это обычно приводит к применению последнего шаблона в вашем файле xslt, поэтому на выходе будет def. Это связано с тем, что оба шаблона имеют одинаковый приоритет, и если ваш процессор xslt не останавливается с ошибкой, стандарт требует, чтобы он применил последний:

Ошибка, если это оставляет более одного подходящего шаблонного правила. Процессор XSLT может сигнализировать об ошибке; если он не сигнализирует об ошибке, он должен восстановиться, выбрав из числа оставшихся соответствующих правил шаблона то, которое встречается последним в таблице стилей.

4 голосов
/ 26 января 2010

Если вы действительно хотите, чтобы ваши шаблоны соответствовали обоим атрибутам , то вам просто нужно настроить match XPATH для выбора атрибуты и поместите отношение к foo в предикате; вместо двух конфликтующих шаблонов, совпадающих на элементе foo с одинаковой специфичностью (которые имеют одинаковый приоритет).

<?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet
   version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

<xsl:template match="/">
  <xsl:apply-templates select="doc/foo"  />
</xsl:template>

<!--When templates match on foo, apply templates for it's attributes -->
<xsl:template match="foo">
    <xsl:apply-templates select="@*"/>
</xsl:template>

<!--Unique template match for the bar attribute -->
<xsl:template match="@bar[parent::foo and .='1']">
  abc
</xsl:template>

<!--Unique template match for the baz attribute -->
<xsl:template match="@baz[parent::foo and .='2']">
  def
</xsl:template>

</xsl:stylesheet>
0 голосов
/ 26 января 2010

Если вы исправите этот XSLT-код (у вас есть проблемы с фильтром) и запустите его, вы должны увидеть:

Защита

Почему? <xsl:apply-templates /> будет соответствовать первому шаблону, который удовлетворяет условию вашего соответствия. Если у вас есть два шаблона, вы должны отличаться от этого, используя этот атрибут <xsl:apply-templates> mode или атрибут <xsl:template> priority:

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

    <xsl:template match="/doc">
        <xsl:apply-templates select="foo" mode="2" />
    </xsl:template>

    <xsl:template mode="1" match="foo[@bar='1']">
        abc
    </xsl:template>

    <xsl:template mode="2" match="foo[@baz='2']">
        def
    </xsl:template>

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