Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a better matched template not chosen?

I have the following xml:

<root xmlns:s="http://example.com/schema">
  <foo>
     <s:bars>
       <s:bar name="normal">bar101</s:bar>
       <s:bar name="special">Foobar</s:bar>
       <s:bar name="super">FuBar</s:bar>
     </s:bars>
  </foo>
</root>

I use the following xslt template to output the bar elements:

  <xsl:template match="root">
    <foos>
      <xsl:apply-templates select="foo/s:bars"/>
    </foos>
  </xsl:template>

  <xsl:template match="s:bars/s:bar[@name='special' or @name='super']">
    <xsl:element name="{@name}">
      <xsl:text>special value:</xsl:text>
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="s:bars/s:bar">
    <xsl:element name="{@name}">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

Strangely enough this outputs the following xml when using the .Net XSLT processor:

<foos>
  <normal>bar101</normal>
  <special>Foobar</special>
  <super>FuBar</super>
</foos>

Apparently the template for s:bars/s:bar[@name='special' or @name='super'] is not used. I expected the following output:

<foos>
  <normal>bar101</normal>
  <special>special value:Foobar</special>
  <super>special value:FuBar</super>
</foos>

I tried adding an extra template to select bars

  <xsl:template match="s:bars">
    <xsl:comment>bars</xsl:comment>
    <xsl:apply-templates />
  </xsl:template>

but that didn't change the result (but did add <!--bars--> to the result so the template gets called.)

I seem to expect something different from the template rules or misunderstand them. Shouldn't a match on an element AND attributes be selected over a match on ONLY an element?

How should I change my XSLT template to get my desired output with the .Net XSLT processor implementation?

like image 937
KennyBOT Avatar asked Dec 15 '25 13:12

KennyBOT


1 Answers

Both templates have the same priority 0.5 (see http://www.w3.org/TR/xslt#conflict) so the XSLT processor can either report an error or take the last one. If you don't get an error then your XSLT processor has taken the last matching template rule. So either change the order or set an explicit priority (e.g. <xsl:template match="s:bars/s:bar[@name='special' or @name='super']" priority="5">) on the one you want to be preferred.

like image 140
Martin Honnen Avatar answered Dec 19 '25 03:12

Martin Honnen