Problems with namespaces?

82 views
Skip to first unread message

XSL Stapler

unread,
Aug 24, 2011, 11:51:37 AM8/24/11
to XSpec
Here is an xspec doc:

<x:description xmlns:x="http://www.jenitennison.com/xslt/xspec"
stylesheet="temp.xsl">
<x:scenario label="Namespace test">
<x:context> <root xmlns="http://www.somenamespace.com"
val="bbbb"/></x:context>
<x:expect><html>333</html></x:expect>
</x:scenario>
</x:description>


Here is temp.xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/
Transform" xmlns:a="http://www.somenamespace.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-
prefixes="#all">
<xsl:variable name="test" select="/a:root/@val" as="xs:string"/>
<xsl:template match="a:root">
<html><xsl:value-of select="$test"/></html>
</xsl:template>
</xsl:stylesheet>

When I run a standalone xml file with the above xslt it transforms
fine. When I run it from Xspec however I get the following error: 'An
empty sequence is not allowed as the value of variable $test'. Any
idea why?

I am running xspec-v0.2 from Oxygen XML editor

Florent Georges

unread,
Aug 24, 2011, 4:16:22 PM8/24/11
to xspec...@googlegroups.com
On 24 August 2011 17:51, XSL Stapler wrote:

Hi,

> <xsl:stylesheet version="2.0" ...


> <xsl:variable name="test" select="/a:root/@val" as="xs:string"/>
> <xsl:template match="a:root">

> ...

> When I run a standalone xml file with the above xslt it
> transforms fine. When I run it from Xspec however I get the
> following error: 'An empty sequence is not allowed as the value
> of variable $test'. Any idea why?

That's because you can not control the value of the global
variables in a test case. You can set their value once per test
suite, but you can not make them dependent on the context of one
test case:

<x:description ...
<x:param name="test" select="333"/>


<x:scenario label="Namespace test">

...

Personally, I don't think that's big a limitation. If you need
to have their values to change from test cases to test cases,
then you might probably use instead a tunnel param in the tule
for the document node.

Regards,

--
Florent Georges
http://fgeorges.org/

http://h2oconsulting.be/

XSL Stapler

unread,
Aug 25, 2011, 3:48:57 AM8/25/11
to XSpec
We have a significant number of global variables, I think all of them
are dependent on the test case they are being invoked against. To
change them to tunnel params in the document node template is
problematic for 2 reasons:

- We would have to declare the param ( <xsl:param name="xxxx"
tunnel="yes"/> ) in every template they are referenced - this would
require a very large number of changes.

- We have a number of different XSL 'starting points', each with their
own document node template (that are invoked depending on the output
format you are trying to create). Currently all these 'starting point'
XSL files reference a single, shared, 'global variables' XSL file. To
change to your suggested model would mean we would have to duplicate
all the variables in every starting point XSL file.

It seems a bit unreasonable to have to rewrite our stylesheets so that
it fits in with the requirements of a test tool?

We also have global, shared, stylesheet params, keys, character-maps,
functions and global xsl:output declarations - are we likely to
experience a similar problem with any of these?

Thanks

Florent Georges

unread,
Aug 25, 2011, 4:10:13 AM8/25/11
to xspec...@googlegroups.com
On 25 August 2011 09:48, XSL Stapler wrote:

Hi,

> We have a significant number of global variables, I think all
> of them are dependent on the test case they are being invoked
> against.

The only way I see then is to create a separate test suite (a
separate XSpec file) for each different set of global variable
values.

> We also have global, shared, stylesheet params, keys,
> character-maps, functions and global xsl:output declarations -
> are we likely to experience a similar problem with any of
> these?

Except for params (which are the same as variables), no,
because those are static components (the "value" of an output
declaration for instance cannot change depending on the main
input tree).

XSL Stapler

unread,
Aug 25, 2011, 6:21:59 AM8/25/11
to XSpec
OK, thanks for the info.

If I have a global variable in the XSL:

<xsl:variable name="test2" as="element()">
<xsl:sequence select="/a:root/a:secondlevel"/>
</xsl:variable>

And the following XML source:

<root xmlns="http://www.somenamespace.com" val="bbbb">
<secondlevel attrValue="nnnn">
<b>nnnnnn</b>
</secondlevel>
</root>

How can I replicate this: <xsl:value-of select="$test2/parent::a:root/
@val"/> using an XSpec global variable?

Florent Georges

unread,
Aug 25, 2011, 9:34:45 AM8/25/11
to xspec...@googlegroups.com
On 25 August 2011 12:21, XSL Stapler wrote:

> If I have a global variable in the XSL:

> <xsl:variable name="test2" as="element()">
> <xsl:sequence select="/a:root/a:secondlevel"/>
> </xsl:variable>

> [...]

> How can I replicate this: <xsl:value-of
> select="$test2/parent::a:root/ @val"/> using an XSpec global
> variable?

There is no mechanism to set the global context for the whole
stylesheet. Just for the one template rule a test case is
testing. The trick is to create a global variable in the XSpec
suite with the same name, which will override the one in the
stylesheet, and to initialize it with the same context:

<x:description ...>

<!-- the context -->
<x:variable name="context">
<a:root val="bbbb">
<a:secondlevel attrValue="nnnn">
<a:b>nnnnnn</a:b>
</a:secondlevel>
</a:root>
</x:variable>

<!-- the global variable, using the context -->
<x:variable name="test" select="$context/@val"/>

<!-- one test case, using the same context -->


<x:scenario label="Namespace test">

<x:context select="$context"/>
<x:expect>
<html>bbbb</html>
</x:expect>
</x:scenario>

</x:description>

If you have a lot of global variable, you can replcae them
from:

<xsl:stylesheet ...>
<xsl:variable name="v1" select="/*/@a"/>
<xsl:variable name="v2" select="/*/*[1]"/>
...

to:

<xsl:stylesheet ...>
<xsl:variable name="input" select="/*"/>
<xsl:variable name="v1" select="$input/@a"/>
<xsl:variable name="v2" select="$input/*[1]"/>
...

so in a specific suite you just have to define the global
variable $input and use it as the context in the test cases:

<x:description ...>
<x:variable name="input">
...
</x:variable>

XSL Stapler

unread,
Aug 25, 2011, 11:37:37 AM8/25/11
to XSpec
We have a number of global variables which act as a pointer to the
document node of an external XML file:

<xsl:variable name="AnotherXml" as="document-node()?"
select="document(concat('../../test_', $Var, '.xml'))" />

This document, stored in $AnotherXml, is then used as the starting
point for numerous other XPath expressions, as well as the 3rd
argument in numerous key() calls.

If I understand you correctly I will need to paste the content of
these XML documents inside each of their corresponding <x:variable>
declarations for this to work? Which also means every time one of
these external files gets updated by a developer the Xspec docs will
also have to get updated.

Florent Georges

unread,
Aug 25, 2011, 12:16:31 PM8/25/11
to xspec...@googlegroups.com

No. That's different than your previous example, where the
variables were initialized against the main input tree. If they
don't use the main input tree, that's not a problem. But you
haven't showed us how $Var is initialized, so maybe it does
depend on the main input tree after all.

That's also why I suggested to create a variable with the main
input tree root, and make the other variables using it, instead
of using the main input tree directly. So in that case you only
have to create one variable in the test suite, in accordance with
the test case context.

But of course, if you have other variables that don't rely on
the main input tree, then that does change anything for them.

Reply all
Reply to author
Forward
0 new messages