p2p.wrox.com Forums

p2p.wrox.com Forums (http://p2p.wrox.com/index.php)
-   BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition ISBN: 978-0-470-19274-0 (http://p2p.wrox.com/forumdisplay.php?f=398)
-   -   Question about template precedence (http://p2p.wrox.com/showthread.php?t=71672)

asc December 1st, 2008 04:52 AM

Question about template precedence
 
Hello I have just begun to play around with XSLT and I have a question about template matching precedence that I haven't been able to figure out myself. That is, I know how to solve this problem to get the desired result, but I since I'm in the "learning phase" I would like to know why the XSLT stylesheet below produces the result below.

The XML-file:
Code:

<?xml version="1.0" encoding="UTF-8"?>
<cars>
    <car>
        <brand>BMW</brand>
        <type>335i</type>
    </car>
    <car>
        <brand>Audi</brand>
        <type>A4 3.0 TDI</type>
    </car>
    <car>
        <brand>Alfa</brand>
        <type>159 3.2 JTS V6</type>
    </car>
</cars>

The XSLT stylesheet:
Code:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="...">
    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>

     <xsl:template match="/">
        <html>
          <body>
            [list]
              <xsl:apply-templates/>
            </ul>
          </body>
        </html>
      </xsl:template>


    <xsl:template match="*"/>


    <xsl:template match="//car[type='335i']">
        <li><xsl:value-of select='brand'/></li> 
    </xsl:template>

</xsl:stylesheet>

The output generated:
Code:

<html>
  <body>
    <ul />
  </body>
</html>

(1) The first thing I'm not quite sure about is if the last two templates are conflicting. Looking at the output it seems that way, but I would have expected, that a more specific match (like the car match) has higher precedence than a more general match (*). Could anyone comment on this?

(2) Under the assumption that the two templates are conflicting, I understand that it depends on the implementation of the XSLT processor if an error is reported or the last of the conflicting templates is chosen. Since my XSLT processor (= XMLSpy) does not report an error, the last matching template should be chosen.

So, in either case I would expect the following output, because
if the templates are conflicting, the third template should be chosen and thus "BMW" should be written to the destination tree and the other cars are not. If, on the other hand, the two templates are not conflicting, then "BMW" should be written to the destination tree by the third template and the other cars match the second template which does nothing.

Code:

<html>
  <body>
    [list]
      <li>BMW</li>
    </ul>
  </body>
</html>

To summarize, my questions are
(1) Are the "<xsl:template match="*"/>" and "<xsl:template match="//car[type='335i']">" templates and conflicting?

(2) Why does the XSLT-script produce an empty list?

I really want to know what is happening here and hoping for your help ;)

Regards,
Alex


samjudson December 1st, 2008 05:02 AM

Your root template matches the root of the document, then tells the stylesheet to apply templates to all irs children.

The first child, the "cars" node, is then matched, on the second template. This template tells it to do nothing else, so that's what it does. No other nodes are therefore being processed.

Change <xsl:template match="*"/> to <xsl:template match="text()"/> - this will probably give you the output you want.

/- Sam Judson : Wrox Technical Editor -/

mhkay December 1st, 2008 05:38 AM

Yes, they are conflicting, because an element that matches //car[...] will also match "*".

The default priority of a template depends on the syntax of the match pattern. The pattern "*" has lower priority than "//car[...]". So in this case the second will always be chosen (assuming it matches).

Your stylesheet produces no output because the template for the document node applies templates to the top-level element (<cars>), and the template rule that matches <cars> is the one with match="*", which doesn't apply-templates to its children.

Incidentally, you don't need "//" at the start of a match pattern. Its only effects are subtle things you almost certainly don't want: (a) it can change the default priority of the template in unexpected ways, and (b) it will only match the car element if the element is part of a document. Just write match="car[type='555i']"

Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer's Reference

asc December 1st, 2008 08:14 AM

Ah, I understand. I was thinking that 'match="/"' matches the top-level element of of the document, but it really means the document root which is not the same as the top level element.

Thank you very much!




All times are GMT -4. The time now is 08:20 AM.

Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.