Unable to cast from XRTreeFrag into XNodeSet

南笙酒味 提交于 2019-12-11 04:53:08

问题


I have the following test code... I am trying to pass a node-set as a param. After many hours, i finally was able to pass it to my template.

How I pass my node-set to the template:

<xsl:call-template name="listing">
    <xsl:with-param name="customData">
        <xsl:apply-templates select="exslt:node-set($data)"/>
    </xsl:with-param>
</xsl:call-template>

How my template receives it:

<xsl:template name="listing">
    <xsl:param name="customData" select="/.."/>
    <xsl:variable name="data">
        <xsl:choose>
            <xsl:when test="not($customData)">
                <xsl:value-of select="/data"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$customData"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <textarea><xsl:copy-of select="$data"></xsl:copy-of></textarea>
</xsl:call-template>

If I set the parameters with a one liner, then it would not complain... example:

<xsl:variable name="data" select="$customData"/>

But as soon as I try to set it like this, it breaks:

<xsl:variable name="data">
   <xsl:value-of select="$customData"/>
</xsl:variable>

Getting this error message: org.apache.xpath.objects.XRTreeFrag cannot be cast to org.apache.xpath.objects.XNodeSet

I was only been able to find another thread dated back in 2000, talk about this similar issue... I need to re-nodeset it back using something like node-set($customData)/* but I tried that, and it was a no go.

EDIT: OK, I can confirm that I successfully passed the node-set inside my template. But I'm still unable to copy it over to my variable... It kept saying that it is still a RTF.

<xsl:template name="listing">
<xsl:param name="customData" as="node-set"/>
<!--<xsl:variable name="data" select="/data"/>-->

<xsl:variable name="data">
    <xsl:choose>
        <xsl:when test="count($customData) != 0">
            <xsl:copy-of select="$customData"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="/data"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

    <textarea><xsl:value-of select="$customData/record[1]"/></textarea>
    <textarea><xsl:value-of select="/data/record[1]"/></textarea>
    <textarea><xsl:value-of select="$data/record[1]"/></textarea>
</xsl:template>

The above test, shows that I can access $customData and the original /data without any problem, they both show the record... but $data is messed up. So that means the copy from $customData to $data wasn't working...

I tried the following ways, none of them work:

<xsl:copy-of select="$customData"/>
<xsl:value-of select="$customData"/>
<xsl:apply-templates select="exslt:node-set($customData)"/>
<xsl:apply-templates select="exslt:node-set($customData)/data"/>

Any idea...?


回答1:


This error message comes from Xalan, which is an XSLT 1.0 processor. If you are using Xalan, then you are probably using Java, which means there is really no reason at all not to move to XSLT 2.0 in the form of Saxon. You will find that XSLT 2.0 removes many of the restrictions of XSLT 1.0, of which this is one of the most irritating.

If there's a good reason why you can't move forward to XSLT 2.0 (and it's hard to think of one), there's a workaround in the form of the exslt:node-set() function, which converts a result-tree fragment (that is, a variable defined using child instructions) into a document node.




回答2:


Got it working, basically rather than using apply-template, i need to pass the RTF as a parameter to the template. That is the only way I got it to work.

<xsl:with-param name="data" select="exslt:node-set($customData)"/>

Using this method, I was able to MODIFY data in XSL level. This is really cool, I basically manipulate the data I want, then i reconstruct the root /, and then I pass my customData to my template function.

So rather than reading data off the root, I read my own modified data (constructed inside XSL).




回答3:


Use of exslt:node-set does indeed suppress the error message org.apache.xpath.objects.XRTreeFrag cannot be cast to org.apache.xpath.objects.XNodeSet

However, the node-set that is created for some reason cannot be used in subsequent XPath expressions; at least it doesn't seem to work with Xalan 2.6.0 / XSLT 1.0 which is the version many people are forced to use for one reason or another.

There is a simple solution: instead of setting the variable to a node-set, set it to the XPath expression instead. Then you can use the dyn:evaluate EXSLT function to evaluate the XPath expression held by the variable.

Your code would look something like this:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:dyn="http://exslt.org/dynamic"
                extension-element-prefixes="dyn"
                exclude-result-prefixes="dyn">

..

    <xsl:variable name="data">
        <xsl:choose>
            <xsl:when test="count(.) != 0">
                <xsl:text>.</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>/data</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <textarea>
         <xsl:value-of select="dyn:evaluate($data)/record[1]"/>
    </textarea>


来源:https://stackoverflow.com/questions/11549947/unable-to-cast-from-xrtreefrag-into-xnodeset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!