This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Giving values to xsl:variable by xml attribute


Ofer--

You're running into trouble actually for two reasons. First, when you 
declare the variable

>This is my static xsl tree
><xsl:variable name="values">
>         <one>1</one>
>         <two>2</two>
></values>

what you have assigned is not actually a node set (despite appearances), 
it's a Result Tree Fragment -- which is like a node set in many respects, 
except you can't query it.

Second, you can't construct XPath queries dynamically, so if

>This is the input xml:
><x value="one"/>
>.
><xsl:value-of name="$values/one"/>
>
>This will work, but what if I want the "one" node to be determined by the
>xml value?

you're stuck ... you can't write an XPath that would say (e.g.) 
$values/{x/@value} with {x/@value} evaluated dynamically.

So how to do what you want? You basically have three choices.

#1 is to use an extension function. Many processors have a function that 
can be used to turn the RTF into a node set. Then you could query it with 
an expression like

<xsl:value-of select="ext:node-set($values)/*[name()= x/@value]"/>

where ext:node-set is your extension function (consult your processor's 
documentation). The */[name()= x/@value] gets around the "dynamic XPath" 
problem. The extension function gets you around the problem with the Result 
Tree Fragment.

[note: in future versions of XSLT, it may not be necessary to use an 
extension function for this.]

#2 is to do essentially what you're doing, but instead of using a variable, 
use the document() function to query the stylesheet itself as a node tree. 
It's done like this:

<my:values xmlns:my="http://mynamespace-declaration-uri";>
         <one>1</one>
         <two>2</two>
<my:values>

Goes in the stylesheet.

Then you can query it like so:

<xsl:value-of select="document('')/*/my:values/*[local-name()= x/@value]"/>

notice the extra step in the location path to get below the xsl:stylesheet 
element. (Using the local-name() function is just a precaution against 
namespace funkiness.)

(We need a name for this idiom. Was it Oliver Becker who first noticed it? 
I've heard it called 'local lookup tables' and such things, but that's 
neither very catchy nor very descriptive.)

(Another note: you could even avoid the my:values element by declaring a 
variable, as you did, and then saying

<xsl:value-of 
select="document('')/*/xsl:variable[@name='values']/*[local-name()= 
x/@value]"/>

but I think you'll agree that's a little misleading because you're not 
actually using the variable as a variable, you're just querying into it as 
a node in your stylesheet.)

Option #3 is to run your process in two steps. The first step generates the 
stylesheet that you run in the second step. This will get you around having 
to do the *[local-name()= x/@value] thing, since your XPath will be 
generated in step 1 and evaluated in step 2. You'll still have to use one 
of the other techniques to get your match. This option is probably 
worthwhile only if your requirements for dynamic processing get really ornate.

I hope this helps.

Regards,
Wendell




>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


======================================================================
Wendell Piez                            mailto:wapiez@mulberrytech.com
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
   Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]