Question

Trying to understand next-match I found an example at xmlplease.com, but when I try it out myself I get an Ambiguous rule match for ..., and I really can't see how it wouldn't get that with this example. How is the third template supposed to take precedence before the other two?

Is the example simply wrong, or am I missing something here?


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>

Sample input

<?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>
Was it helpful?

Solution 2

Well basically given your XSLT you have the same match patterns twice, you have xsl:template match="product" and xsl:template match="product[@id = 'p2']" and then you have xsl:template match="product|product[@id = 'p2']" again. That way there are certainly ambiguous matches for all your product input elements. So I agree with you, with a stylesheet that has the same match pattern twice on different templates, you will get that error or warning of ambiguity. However the processor can choose to only emit a warning and to take the last of the templates. That is what Saxon 9 does for instance, it says something like

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

but then writes an output of

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

OTHER TIPS

The XSLT 2.0 spec says that it's an error to have two templates with the same precedence and priority that both match the same node, and that's what's happening here. The spec gives a number of options for what should happen (and Saxon has configuration options allowing you to choose various strategies) but if you want your code to be portable and error-free, the best approach is to add explicit priorities to each rule using the priority attribute on xsl:template. (Higher number means higher priority).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top