Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

tsuji - you are beaten - unfixable problem (?) 1

Status
Not open for further replies.

simonchristieis

Programmer
Jan 10, 2002
1,144
GB
Well, I've been on this for a bit, and I can't see a way round it, so my last resort is tsuji (or others) in tek-tips.

I am trying to create a node set dynamically within a variable, but then I want to run xpath against that node set, perhaps it's easier to just show you some code to explain:



Code:
<xsl:template match="/">
<xsl:variable name="node">
<xsl:apply-templates select="." mode="create"/>
</xsl:variable>

Result: <xsl:value-of select="$node/result/second"/>

</xsl:template>

<xsl:template match="*" mode="create">
<result>
<first>1</first>
<second>2</second>
</result>
</xsl:template>

The error I am recieving is:

org.apache.xpath.objects.XRTreeFrag cannot be cast to org.apache.xpath.objects.XNodeSet

I am using the xalan parser, and cant use extensions.

Anyone know any clever workarounds ?

Thanks in advance

Simon
 
Not sure why you cannot use extensions, since node-set is a readily available extension for xalan.

Here is a decent article about the node set problem.

Tom Morrison
 
[0] I have an unadmitted xslt-phobia just because a solution to every concrete case is a new experience and a challenge anew to "work on". Aggravated by finding a handle I am familiar with!

[1] The concrete requirement can be more simply resolved by using a path of least work: namely treating the template with that specific mode as a lookup table. The match attribute is of not much use and is redundant in the solution proposed.
[tt]
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="[ignore][/ignore]">
<xsl:eek:utput method="text" />

<xsl:template match="/">
<xsl:text>Result: </xsl:text>
<xsl:value-of select="document('')/xsl:stylesheet/xsl:template[@mode='create']/result/second"/>
</xsl:template>

<xsl:template match="*" mode="create">
<result>
<first>1</first>
<second>2</second>
</result>
</xsl:template>
</xsl:stylesheet>[/tt]

[2] From the structure above, it is clear that the xsl:template can also be replaced by a less confusing tag because it is just used as a container of a lookup table embedded in the stylesheet itself.
 
Thanks for your responses, my fault I'm afraid, I simplified the code too much, a simple look up wont suffice, because I want the apply-templates to create dynamic xml:

xml
Code:
<foo>
<bar>1</bar>
<bar>2</bar>
</foo>

Code:
<xsl:template match="/">
<xsl:apply-templates select="foo/bar"/>
</xsl:template>

<xsl:template match="bar">
<xsl:variable name="node">
<xsl:apply-templates select="." mode="create"/>
</xsl:variable>

Result: <xsl:value-of select="$node/result/second"/>

</xsl:template>

<xsl:template match="*" mode="create">
<result>
<first><xsl:value-of select="document('')/xsl:stylesheet/dataIsland/data[id=current()]"/></first>
</result>
</xsl:template>

<dataIsland>
<data id="1">barr</data>
<data id="2">borr</data>
</dataIsland>

The problem with adding extensions would be persuading IT support to upgrade and support the servers, in my environment, this just wont happen.

Any other ideas / work arounds / even hacks ???

Thanks

Simon

 
This is how you can do it. I try to use variable to make a better transition. Named template is used instead of mode. Parameters passing to the named template play a important functional role.
[tt]
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="[ignore][/ignore]"
xmlns:xdata="urn:tek-tips-1452289:lookup"
>
<xsl:eek:utput method="text" />

<xsl:template match="/">
<xsl:apply-templates select="foo/bar"/>
</xsl:template>

<xsl:template match="bar">
<xsl:text>Result: </xsl:text>
<xsl:variable name="xnode">
<xsl:call-template name="create2">
<xsl:with-param name="x" select="normalize-space(.)" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$xnode" />
<xsl:text>&#x0d;&#x0a;</xsl:text>
</xsl:template>

<xsl:template name="create2">
<xsl:param name="x" />
<xsl:value-of select="document('')/xsl:stylesheet/xdata:dataIsland/xdata:data[@id = $x]" />
</xsl:template>

<xdata:dataIsland>
<xdata:data id="1">barr</xdata:data>
<xdata:data id="2">borr</xdata:data>
</xdata:dataIsland>

</xsl:stylesheet>
[/tt]
 
I'm gonna thank you again for your help.

I should have just posted the code instead of just reliving it through simpler code.

I want to return 2 values from the mode="create" template, thats why I wanted to create a new xml tree within the variable.

k5tm's post was exactly the answer I was looking for, but I couldn't do that, so I was looking for a workaround.

I have solved my problem by delimiting the 2 results to be returned with a specific string and then using substring before / after to get the values out again, it's a hack, I know.

Thanks for you help anyway.

Regards

Simon

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top