Разве это неоднозначное совпадение правил не должно произойти?

Пытаясь понять next-match Я нашел пример на xmlplease.com, но когда я попробую сам, я получаю Ambiguous rule match for ...и я действительно не вижу, как это не получится с этим примером. Как третий шаблон должен иметь приоритет перед двумя другими?

Это просто неправильный пример или я что-то здесь упускаю?


XSLT

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes" />
    <xsl:template match="/">
        <PRODUCTS>
            <xsl:apply-templates />
        </PRODUCTS>
    </xsl:template>
    <xsl:template match="product">
        <PRODUCT id="{@id}" price="{@price}" stock="{@stock}" />
    </xsl:template>
    <xsl:template match="product[@id = 'p2']">
        <PRODUCT id="{@id}" price="{@price * 1.25}" stock="{@stock}" />
    </xsl:template>
    <xsl:template match="product|product[@id = 'p2']">
        <xsl:comment>
            <xsl:value-of select="concat(' ', @name, ' ')" />
        </xsl:comment>
        <xsl:text>&#xA;</xsl:text>
        <xsl:next-match />
    </xsl:template>
</xsl:stylesheet>

Пример ввода

<?xml version="1.0"?>
<products>
    <product id="p1" name="Delta" price="3250" stock="4" />
    <product id="p2" name="Golf" price="1000" stock="5" />
    <product id="p3" name="Alpha" price="1200" stock="19" />
</products>

2 ответа

Решение

Ну, в принципе, учитывая ваш XSLT, вы имеете одинаковые шаблоны совпадений дважды, у вас есть xsl:template match="product" а также xsl:template match="product[@id = 'p2']" и тогда у вас есть xsl:template match="product|product[@id = 'p2']" снова. Таким образом, безусловно, есть неоднозначные совпадения для всех ваших product элементы ввода. Поэтому я согласен с вами: с таблицей стилей, в которой дважды используется один и тот же шаблон соответствия для разных шаблонов, вы получите эту ошибку или предупреждение о неоднозначности. Однако процессор может выбрать только выдачу предупреждения и получение последнего из шаблонов. Вот что делает Saxon 9, например, он говорит что-то вроде

Recoverable error
  XTRE0540: Ambiguous rule match for /products/product[1]
Matches both "element(Q{}product)" on line 14 of
  file:/C:/Users/Martin%20Honnen/Documents/xslt/test2014012101.xsl
and "element(Q{}product)" on line 8 of
  file:/C:/Users/Martin%20Honnen/Documents/xslt/test2014012101.xsl
Recoverable error
  XTRE0540: Ambiguous rule match for /products/product[2]
Matches both "product|product[@id = 'p2']" on line 14 of
  file:/C:/Users/Martin%20Honnen/Documents/xslt/test2014012101.xsl
and "product[@id = 'p2']" on line 11 of
  file:/C:/Users/Martin%20Honnen/Documents/xslt/test2014012101.xsl
Recoverable error
  XTRE0540: Ambiguous rule match for /products/product[3]
Matches both "element(Q{}product)" on line 14 of
  file:/C:/Users/Martin%20Honnen/Documents/xslt/test2014012101.xsl
and "element(Q{}product)" on line 8 of
  file:/C:/Users/Martin%20Honnen/Documents/xslt/test2014012101.xsl

но затем пишет вывод

<PRODUCTS>
    <!-- Delta -->
   <PRODUCT id="p1" price="3250" stock="4"/>
    <!-- Golf -->
   <PRODUCT id="p2" price="1250" stock="5"/>
    <!-- Alpha -->
   <PRODUCT id="p3" price="1200" stock="19"/>
</PRODUCTS>

Спецификация XSLT 2.0 гласит, что ошибкой является наличие двух шаблонов с одинаковым приоритетом и приоритетом, которые оба соответствуют одному и тому же узлу, и это то, что здесь происходит. Спецификация дает ряд опций для того, что должно произойти (и Saxon имеет опции конфигурации, позволяющие выбирать различные стратегии), но если вы хотите, чтобы ваш код был переносимым и безошибочным, лучший подход - это добавить явные приоритеты к каждому правилу, используя атрибут приоритета в xsl:template. (Более высокое число означает более высокий приоритет).

Другие вопросы по тегам