This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Giving values to xsl:variable by xml attribute
- To: xsl-list at lists dot mulberrytech dot com
- Subject: Re: [xsl] Giving values to xsl:variable by xml attribute
- From: Wendell Piez <wapiez at mulberrytech dot com>
- Date: Thu, 04 Oct 2001 11:24:51 -0400
- Reply-To: xsl-list at lists dot mulberrytech dot com
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