user2968553
user2968553

Reputation: 33

Value is empty while using XSLT file

I'm currently having a problem with a transformation of a file. Does anyone could help me to understand what the problem is?

My source file is:

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
    <fields>
        <field name="A">
            <field name="0216"><value>abcde</value></field>
        </field>
    <fields>
</xfdf>

My XSLT file is:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <personalData>
            <personal>
                <name>
                    <xsl:value-of select="//field[@name='A']//field[@name='0216']//value"/>
                </name>
            </personal>
        </personalData>
    </xsl:template>
</xsl:stylesheet>

The output file is:

<?xml version="1.0" encoding="UTF-8"?>
<personalData>
    <personal>
        <name/>
    </personal>
</personalData>

I don't understand why the value is empty...

Thank you in advance,

Maxime

Upvotes: 3

Views: 101

Answers (1)

Mark Veenstra
Mark Veenstra

Reputation: 4739

Your input XML has a default namespace declared xmlns="http://ns.adobe.com/xfdf/". This means that all elements that are unprefixed belong to this namespace.

Therefore you should also declare the namespace in your XSLT. Preferable with a prefix, like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xdf="http://ns.adobe.com/xfdf/" exclude-result-prefixes="xdf">

The exclude-result-prefixes="xdf", will not output the namespace into your result XSLT. Now you have the namespace declared and you can select nodes belonging to this namespace with this prefix, like this:

<xsl:value-of select="//xdf:field[@name='A']//xdf:field[@name='0216']//xdf:value"/>

Also note that the use of // will go through all elements everytime you use it. To be more efficient write a XPath that will just find the node directly:

<xsl:value-of select="//xdf:field[@name='A']/xdf:field[@name='0216']/xdf:value"/>

The first // will start searching from the root over all elements. After finding xdf:field with @name equal to value A it will go done the three, because of using /.

You can even get rid of the first //:

<xsl:value-of select="xdf:xfdf/xdf:fields/xdf:field[@name='A']/xdf:field[@name='0216']/xdf:value"/>

Note that it did not start with a /, because you are already on the root withing your template match.

Upvotes: 3

Related Questions