1) An xsl:variable or xsl:param causes an error if it is not
"declared" before it is used.
This works:
<xsl:variable name="test">This is a test</xsl:variable>
<xsl:value-of select="$test"/>
The following does not work. It works with MSXML4, and I believe that
XSLT says it should work. The variable is "created" after it is
displayed, but it is in the correct scope:
<xsl:value-of select="$test"/>
<xsl:variable name="test">This is a test</xsl:variable>
2) If I call msxsl:node-set on an entity that is already a node-set,
the parser throws an error. MSXML4 tolerates this behavior. I think
that if it's already a node set, it should just return the same
node-set.
This code works:
<xsl:variable name="thing">
<value>1</value>
<value>2</value>
</xsl:variable>
<xsl:variable name="thing2" select="msxsl:node-set($thing)"/>
<xsl:copy-of select="$thing2"/>
This code does not work:
<xsl:variable name="thing">
<value>1</value>
<value>2</value>
</xsl:variable>
<xsl:variable name="thing2" select="msxsl:node-set($thing)"/>
<xsl:copy-of select="msxsl:node-set($thing2)"/>
thanks,
Keith
"Keith Langer" <tana...@aol.com> wrote in message
news:15c7b652.03020...@posting.google.com...
> In case someone from Microsoft reads this, I've found a few behaviors
> in the .Net XSLT parser which may be bugs:
>
> 1) An xsl:variable or xsl:param causes an error if it is not
> "declared" before it is used.
>
> The following does not work. It works with MSXML4, and I believe that
> XSLT says it should work. The variable is "created" after it is
> displayed, but it is in the correct scope:
>
> <xsl:value-of select="$test"/>
> <xsl:variable name="test">This is a test</xsl:variable>
I think that should be an error. xsl:variable is allowed as a top-most
element, giving the variable global scope to all template rules. Because
xsl:value-of is not allowed as a top-most element, this infers that
variables must be declared before being used. You can still declare a
stylesheet-scoped variable after the template is declared:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="$foo"/>
</xsl:template>
<xsl:variable name="foo" select="'test'"/>
</xsl:stylesheet>
This makes sense, though: the only restriction on the placement of an
xsl:variable with stylesheet scoping is that it can only have a parent
element "xsl:stylesheet" or "xsl:transform", so its index position relative
to sibling elements is irrelevant. This behavior should be consistent,
then, when declaring variables at the template level. Convention for
various programming languages indicates that variables are declared before
used, and all examples in the XSLT recommendation indicate declaration
before use. The XSLT recommendation is ambiguous as to implementation, so
Microsoft is free to choose an implementation that makes sense.
> 2) If I call msxsl:node-set on an entity that is already a node-set,
> the parser throws an error. MSXML4 tolerates this behavior. I think
> that if it's already a node set, it should just return the same
> node-set.
msxsl:node-set() is an extension function, and as such is not part of the
XSLT recommendation. However, the documentation [1] is pretty clear that it
only converts a result tree fragment or node tree, not a node-set.
Personally, I would rather the error condition and not toleration of a
programming mistake.
--
Kirk Allen Evans
Author, "XML And ASP.NET", New Riders Publishing
www.xmlandasp.net
http://dotnetweblogs.com/kaevans
I checked the XSLT specification, and it does say that variables
declared inside templates are "visible for all following siblings and
their descendants". I also found that the code didn't work the way I
thought it would in MSXML4. Inside a template, the variables were only
recognized by following siblings, but as a child of xsl:stylesheet they
were recognized after their binding (when used by another variable,
since copy-of is not allowed at the top level). However, since the same
variable/param name cannot be bound twice within the same scope, it
wouldn't seem to cause any harm to allow binding after use (and it would
be consistent with the top-level bindings where this behavior is
permitted).
As far as the use of msxsl:node-set(), since this was not part of the
XSLT 1.0 recommendation, it is clearly up to the implementor. So what
you refer to as a "programming error" is really only an error if the
implementor decides it to be an error. The authors of MSXML4 decided
not to make this an error, whereas the authors of .Net decided to make
this an error.
Keith
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
I found a concrete example of the problem I was trying to describe
earlier. If I parse the following template with .Net, I get the error
"the variable or param 'test1' is either not defined or it is out of
scope. By simply moving the binding for test1 prior to the binding of
tree1, the error disappears. Since this variable is a child of
xsl:stylesheet, I would expect this behavior to be order-independent.
The problem seems to happen when the referring variable is at least two
layers deeper than the global variable.
Keith
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
>
<xsl:output method="xml"/>
<xsl:variable name="tree1">
<xsl:variable name="test">
<xsl:copy-of select="$test1"/>
</xsl:variable>
</xsl:variable>
<xsl:variable name="test1">test</xsl:variable>
<xsl:template match="/"/>
</xsl:stylesheet>
--
Kirk Allen Evans
Author, "XML And ASP.NET", New Riders Publishing
www.xmlandasp.net
http://dotnetweblogs.com/kaevans
"Keith Langer" <tana...@aol.com> wrote in message
news:ONihzNtzCHA.616@TK2MSFTNGP11...
I modified the example slightly, to make it more realistic:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
>
<xsl:output method="text"/>
<xsl:variable name="tree1">
<xsl:variable name="test">
<xsl:copy-of select="$test1"/>
</xsl:variable>
<xsl:copy-of select="$test"/>
</xsl:variable>
<xsl:variable name="test1">test</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select="$tree1"/>
</xsl:template>
</xsl:stylesheet>
With MSXML3/4, SAXON 6.5.2, XALAN C 1.3, the result is:
test
With the .Net XSLT processor the result is an exception with the following
message:
"Unhandled Exception: System.Xml.XPath.XPathException: The variable or param
'test1' is either not defined or it is out of scope."
=====
Cheers,
Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
"Kirk Allen Evans" <kae...@nospamxmlandasp.net> wrote in message
news:up$aGStzCHA.2188@TK2MSFTNGP10...
Keith