xmlxslt

Confusion with xslt:apply-templates


I do not understand how apply-templates works in XSLT.

Now I have this XML document:

<?xml version="1.0" encoding="UTF-8"?>
<people>
    <person>
        <name>John Doe</name>
        <age>30</age>
        <occupation>Software Engineer</occupation>
    </person>
    <person>
        <name>Jane Smith</name>
        <age>28</age>
        <occupation>Graphic Designer</occupation>
    </person>
    <person>
        <name>Sam Brown</name>
        <age>35</age>
        <occupation>Data Analyst</occupation>
    </person>
</people>

And this XSLT:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <!-- Output -->
    <xsl:output method="html" />
    
    <!-- Default template -->
    <xsl:template match="/">
        <html>
            <body>
                <xsl:apply-templates />
            </body>
        </html>
    </xsl:template>
    
    <!--  Adding ages -->
    <xsl:template  match="person">
        <p>
            <xsl:value-of select="./name/text()" />
        </p>
    </xsl:template>
    
    <!-- Adding names -->
    <xsl:template  match="age">
        <p>
            <xsl:value-of select="./text()" />
        </p>
    </xsl:template>

</xsl:stylesheet>

When I run it, he result I get is this:

<html>
   <body>
      
      <p>John Doe</p>
      
      <p>Jane Smith</p>
      
      <p>Sam nkmk</p>
      
   </body>
</html>

Which is unexpected since I want both the names and the ages of the people, because i defined both templates.

In one of the answers to this question, the following is said the XSLT default template rules are defined in such a way that, by default, they will match the top node of the document and then recursively process each of the child nodes, all the way to the bottom, well fair enough, so technically one would expect that the person node is processed, then it's children, and since there is a template for age, the age should be added to the html, yet it doesn't. (Also, according to the first answer of this question, it should even print the name and occupation since i did not define a template that matches text, like so <xsl:template match="text()">).

All of this is very confusing to me given that i am new to XSLT.

Could you please explain to me what is going on here?


Solution

  • You are missing an important part of your quote, which is "by default".

    Your template matching person overrides the default built-in template - and it does not apply templates to the age (or any other) child of person. Therefore the template matching age is never instantiated, and neither are the built-in templates that would otherwise process the other children of person.