Newbee
Newbee

Reputation: 43

xpath within xslt yields different result from direct evaluation of xpath

I have this simple xml document

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://example.org/attributes">
    <record>
        <codice_fiscale>IT07654930130</codice_fiscale>
        <indirizzo tipo="casa">Viale Carlo Espinasse 5, Como</indirizzo>
    </record>
    <n:record xmlns:n="http://test.com/records">
        <n:codice_fiscale>IT87654770157</n:codice_fiscale>
        <n:indirizzo tipo="ufficio">Via Biancospini 20, Messina</n:indirizzo>
    </n:record>
    <record>
        <codice_fiscale>IT471142131</codice_fiscale>
        <indirizzo tipo="ufficio">Via Chiasserini 88B, Firenze</indirizzo>
        <test>
            <nummeroo>01-000-000</nummeroo>
            <nummeroo>02-000-000</nummeroo>
        </test>
        <test>
            <nummeroo>03-000-000</nummeroo>
            <nummeroo>04-000-000</nummeroo>
        </test>
        <stuff>other stuff</stuff>
    </record>
    <things>
        <nummero>08-000-000</nummero>
        <nummero>09-000-000</nummero>
    </things>
</root>

The following xslt 2.0 stylesheet should output the names of all elements, that have at least one leaf-node as a child.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="no" />
    <xsl:strip-space elements="*"/>
    <xsl:template match="//*[child::*[not(*)]]">
        <xsl:value-of select="concat(name(), '&#xa;')" />
    </xsl:template>
</xsl:stylesheet>

I use the omit-xml-declaration and I strip alle whitespace to get a simple text document. Concatenation with '&#xa;' gives me a newline.

Applied to the above mentioned xml document the xslt yields the following result

record
n:record
record
things

Using the xpath 2.0 expression of the template within the stylesheet, i.e.

//*[child::*[not(*)]]

in conjunction with the name()-function to get the element name as a string, i.e.

//*[child::*[not(*)]]/name()

I get the following result (using different editors / xpath 2.0 evaluators)

record
n:record
record
test
test
things

Using the xslt 2.0 stylesheet and directly evaluating the xpath 2.0 expression with an editor yield different results!

I would expect the results to be exactly the same. The stylesheet and the direct evaluation of the xpath //*[child::*[not(*)]]/name() are essentialy the same and should deliver the same text output.

The xpath expression and the stylesheet are very simple and yet I am not able to figure out why the evaluation of the two yield different results.

Has anyone an idea why the two evaluations yield different results?

Upvotes: 3

Views: 102

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116959

A match pattern is not the same thing as a select expression.

What happens with your stylesheet is this:

  • First, the built-in template rules are applied to the / root node.

  • Then, using the built-in recursion, the same built-in templates are applied to the root root element.

  • Next, your template kicks in and processes the nodes that are children of the root element - and here the processing stops, because your template does not contain an xsl:apply-templates instruction.

Note that a leading // is ignored in a match pattern.

Upvotes: 3

Related Questions