Subject: document(), attribute and name() match
Posted By: perropicante Post Date: 6/13/2003 8:11:48 PM
I've got a relatively simple concept going here: I have one xml document with tags that I want to translate into more meaningful words. The translations are in another xml document. An XSL transformation takes care of matching the tag to its translation.

Here's (part of) the XML document that needs its tags translated.
<?xml version="1.0" encoding="UTF-8"?>
<NewDataSet>
    <Person>
        <id>1</id>
        <firstname>Michael</firstname>
        <lastname>Gradek</lastname>
        <birthdate>1980-11-13T00:00:00.0000000-05:00</birthdate>
    </Person>
</NewDataSet>

Here's the XML document that does the translation
<?xml version="1.0" encoding="UTF-8"?>
<localization>
    <datatranslations>
        <element name="firstname">
            <en>First Name</en>
            <fr>Prénom</fr>
        </element>
        <element name="lastname">
            <en>Last Name</en>
            <fr>Nom</fr>
        </element>
        <element name="birthdate">
            <en>Birth Date</en>
            <fr>Date de Naissance</fr>
        </element>
    </datatranslations>
</localization>


Here's the XSL that fails...
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:param name="localization_url" select="'blackbook_localization.xml'" />
<xsl:variable name="trans_doc" select="document($localization_url)/localization/datatranslations" />


<xsl:template match="/">
    <xsl:call-template name="simpledisplay" />
</xsl:template>


<xsl:template name="simpledisplay">
    <xsl:for-each select="//NewDataSet/*">
        <div style="border: 1px solid #FF0000;">
            <xsl:for-each select="*[not(contains(name(), 'id'))]">
                <xsl:value-of select="name()" />:
                <xsl:value-of select="$trans_doc/element[@name=name()]/en" />:
                <xsl:value-of select="." />
                <br />
            </xsl:for-each>
        </div>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>


The problem is the line
<xsl:value-of select="$trans_doc/element[@name=name()]/en" />
It returns nothing.

$trans_doc/element works properly, I'm able to iterate through its contents.
All the @name attributes have values, and all the calls to name() also return the proper values.

If I type <xsl:value-of select="$trans_doc/element[@name='firstname']/en" />, I get the expected result, same for <xsl:value-of select="$trans_doc/element[@name='lastname']/en" />.

But when I use name() instead of hardcoding the value, it fails... What am I doing wrong?

Thanks for your help!
Mike
Reply By: armmarti Reply Date: 6/14/2003 4:56:31 AM
Hi,
the trick is that in the XPath $trans_doc/element[@name=name()] the function "name()" returns the name of the context node, which is "element", so you compare attribute values with string "element". Replace the line with the following and it must work:

<xsl:value-of select="$trans_doc/element[@name=name(current())]/en" />

Now, you compare the attribute value with the current node's name.

Regards,
Armen
Reply By: perropicante Reply Date: 6/14/2003 1:33:22 PM
Thanks, it worked great. And thanks for the explanation ;)

Mike
Reply By: JavaBurre Reply Date: 9/10/2003 8:29:17 AM
I have a simular problem so I post it to this topic.

In my situation the value to retrieve is in an attribute.
So I try something like this:

<xsl:value-of select="$trans_doc/element[@name=name(current())]@en"/>

But when I run this I get the error (java Xalan):
Fatal Error! Extra illegal tokens: '@', 'en'
Fatal Error! Fatal error during transformation Cause: Fatal error
during transformation
Without the attribute part it processes (but off course not the wanted result).

What did I do wrong ?

Regards,

JavaBurre

Reply By: Yehuda Reply Date: 9/10/2003 8:53:18 AM
I believe you are missing a '/' before the @.  I think you want this:

<xsl:value-of select="$trans_doc/element[@name=name(current())]/@en"/>

Yehuda
Reply By: falmouth Reply Date: 11/16/2004 11:59:39 AM
I have a problem along the sames lines as this. My present XSL code is:

<xsl:element name="test">
    <xsl:choose>
        <xsl:when test="$structure/*[@id=name(current())]"><xsl:value-of select="$structure/*[@id=name(current())]/@label" /></xsl:when>
        <xsl:otherwise>unknown</xsl:otherwise>
    </xsl:choose>
</xsl:element>

The above code works fine. However, I really want it to return the name() of the matching node, rather than the value of its @label attribute - but, when I change @label to name(), I get the following error:

NodeTest expected here. $structure/*[@id=name(current())]/-->name<--()

Does anyone have any suggestions or alternative solutions?

Reply By: jkmyoung Reply Date: 11/16/2004 12:57:29 PM
name is a function; put the name around the rest eg:

select="name($structure/*[@id=name(current())])"

Reply By: falmouth Reply Date: 11/16/2004 2:05:35 PM
Perfect! Thank you so much. I spent most of the day trying to work that out.

So, when it comes to XSL functions, such as name(), you specify your XPath between the brackets! Worth remembering. Thanks!

Reply By: joefawcett Reply Date: 11/17/2004 6:14:07 AM
If you don't specify a path then it uses the context node.


--

Joe (Microsoft MVP - XML)

Go to topic 22218

Return to index page 713
Return to index page 712
Return to index page 711
Return to index page 710
Return to index page 709
Return to index page 708
Return to index page 707
Return to index page 706
Return to index page 705
Return to index page 704