tostinni Posted November 30, 2006 Share Posted November 30, 2006 Hi Everybody,After reading the tutorial about XSLT, I went and tried to convert a little XML into a very simple HTML table but I'm stuck with something I don't understand.So here's the XML <?xml version="1.0"?><people_list> <quantity>2</quantity> <peoples> <people> <name>John</name> <age>25</age> </people> <people> <name>Steve</name> <age>30</age> </people> </peoples></people_list> And here's the XSLT I wrote: <?xml version="1.0" encoding="ISO-8859-1"?><xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="html" indent="yes"/> <xsl:template match="peoples"> <table> <tr> <td>Name</td> <td>Age</td> </tr> <xsl:for-each select="people"> <tr> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="age"/></td> </tr> </xsl:for-each> </table></xsl:template></xsl:stylesheet> When I realize the transformation, I get 2<table><tr><td>Name</td><td>Age</td></tr><tr><td>John</td><td>25</td></tr><tr><td>Steve</td><td>30</td></tr></table> So everything is pretty as I wished excepted the "2" which came from the quantity element of my XML.I don't understand why it shows up and how can I exclud/avoid it ?I thought that putting a template that would apply to peoples will hide it but it doesn't work :)Any idea of what I'm doing wrong ?Thanks a lot for the help. Link to comment Share on other sites More sharing options...
boen_robot Posted November 30, 2006 Share Posted November 30, 2006 Define some sort of root template that will only apply the appropriate one and (optionally) will add some wrappers around the table.Try it like that: <?xml version="1.0" encoding="ISO-8859-1"?><xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="html" indent="yes"/><xsl:template match="/"><!--Add anything you wish to appear before the table--><xsl:apply-templates select="peoples"/><!--Add anything you wish to appear after the table--></xsl:template> <xsl:template match="peoples"> <table> <tr> <td>Name</td> <td>Age</td> </tr> <xsl:for-each select="people"> <tr> <td><xsl:value-of select="name"/></td> <td><xsl:value-of select="age"/></td> </tr> </xsl:for-each> </table></xsl:template></xsl:stylesheet> XSLT has a few build in templates that allow a good and easy workflow. Two of those templates are <xsl:template match="*|/"> <xsl:apply-templates/></xsl:template> and <xsl:template match="text()|@*"> <xsl:value-of select="."/></xsl:template> Unless you create your own template to override those ones, they will get executed.Scince you didn't had a rule for your root node, the templates for other elements are applied. Scince there isn't a template for <quantity>, a template is executed for it's inner nodes. The only inner node is the text node, which according to the second built-in template is just written. Link to comment Share on other sites More sharing options...
tostinni Posted November 30, 2006 Author Share Posted November 30, 2006 Hi boen_robot,Thanks a lot for your reply, in fact I thought something was missing about root template, but didn't knew how to create it, you help me a lot.I understood the template you put for "peoples" but when I apply it to my doc, I didn't have any output...Is something missing ?Edit:If I change <xsl:template match="/"> <xsl:apply-templates select="peoples"/></xsl:template> By <xsl:template match="/"> <xsl:apply-templates select="//peoples"/></xsl:template> It works, I think the confusing part for me is that it's not nodename that select all node matching the name but //nodename.The only strange thing is that the first <xsl:template match="/"> should have taken all child of root element which I thought was people_list but it seems not to be root... Link to comment Share on other sites More sharing options...
boen_robot Posted December 1, 2006 Share Posted December 1, 2006 Opps. Busted. You're right. It had to be either "//peoples" or another explicit XPath expression to limit the execution (for example "/*/peoples" will only execute the template for "peoples" who are childs of the root element). The way I wrote it would have executed the tepmlate if the root element was "peoples".Right again, the root and root element are two different things. The root includes the root element, alongside any processing instructions and comments that might appear before the root element. "/*" on the other hand maches only the root element. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now