Java 为什么可以';我是否在XPath表达式中使用exsl:node set/set:distinct来检索节点的值?
在xslt样式表中,我使用方法Java 为什么可以';我是否在XPath表达式中使用exsl:node set/set:distinct来检索节点的值?,java,xslt,xpath,xerces,xalan,Java,Xslt,Xpath,Xerces,Xalan,在xslt样式表中,我使用方法exsl:node set和set:distinct从包含结果树片段的变量中访问和筛选唯一节点。 我可以将这些节点的值写入输出文件,例如: <xsl:variable name="myNodes"> <xsl:call-template name="getNodes"/> </xsl:variable> <xsl:for-each select="set:distinct(exsl:node-set($myNodes)
exsl:node set
和set:distinct
从包含结果树片段的变量中访问和筛选唯一节点。
我可以将这些节点的值写入输出文件,例如:
<xsl:variable name="myNodes">
<xsl:call-template name="getNodes"/>
</xsl:variable>
<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
<xsl:value-of select="."/>
</xsl:for-each>
正如预期的那样,键的值将写入输出中。
但是,如果尝试在XPath表达式中使用值,则会失败:
<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
<xsl:variable name="result" select="/tree//somenode[@key = current()]"/>
<xsl:value-of select="$result"/>
</xsl:for-each>
现在,输出是空的,而我知道输入xml中有一个“somenode”,应该由XPath表达式选择,它的值不是空的
现在我的问题是:为什么会发生这种情况
我使用的是Java1.6、Xerce2.7和Xalan2.7
更新:
根据要求,示例的一些数据如下:
xml文档包含:
<tree>
<somenode key="123"/>
<num>123</num>
<num>0815</num>
</tree>
123
0815
getNodes模板:
<xsl:template name="getNodes">
<xsl:for-each select="/tree/num">
<xsl:element name="key">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:template>
这里有一个转换,它可以实现与您想要的接近的功能:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
xmlns:exsl="http://exslt.org/common"
>
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:variable name="myNodes">
<xsl:call-template name="getNodes"/>
</xsl:variable>
<xsl:variable name="vDoc" select="/"/>
<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
<xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
<xsl:copy-of select="$result"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="getNodes">
<xsl:for-each select="/tree/num">
<xsl:element name="key">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<tree>
<somenode key="123"/>
<num>123</num>
<num>0815</num>
</tree>
<somenode key="123"/>
应用于提供的XML文档时:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
xmlns:exsl="http://exslt.org/common"
>
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:variable name="myNodes">
<xsl:call-template name="getNodes"/>
</xsl:variable>
<xsl:variable name="vDoc" select="/"/>
<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
<xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
<xsl:copy-of select="$result"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="getNodes">
<xsl:for-each select="/tree/num">
<xsl:element name="key">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<tree>
<somenode key="123"/>
<num>123</num>
<num>0815</num>
</tree>
<somenode key="123"/>
123
0815
产生所需结果:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
xmlns:exsl="http://exslt.org/common"
>
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:variable name="myNodes">
<xsl:call-template name="getNodes"/>
</xsl:variable>
<xsl:variable name="vDoc" select="/"/>
<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
<xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
<xsl:copy-of select="$result"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="getNodes">
<xsl:for-each select="/tree/num">
<xsl:element name="key">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<tree>
<somenode key="123"/>
<num>123</num>
<num>0815</num>
</tree>
<somenode key="123"/>
注意事项:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
xmlns:exsl="http://exslt.org/common"
>
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:variable name="myNodes">
<xsl:call-template name="getNodes"/>
</xsl:variable>
<xsl:variable name="vDoc" select="/"/>
<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
<xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
<xsl:copy-of select="$result"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="getNodes">
<xsl:for-each select="/tree/num">
<xsl:element name="key">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
<tree>
<somenode key="123"/>
<num>123</num>
<num>0815</num>
</tree>
<somenode key="123"/>
,中访问源XML文档,因为此指令将当前节点设置为另一文档中的节点,即由exsl:node-set()创建的临时树
$vDoc
中捕获源XML文档,然后通过此变量访问
中的源XML文档
没有文本节点的后代,因此没有字符串值。对其使用
将不会产生任何输出。这就是为什么我们在这里使用
——它复制完整的元素,然后我们看到结果此样式表与您想要的样式表相同,无需扩展:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="NumByValue" match="num" use="."/>
<xsl:template match="num[count(.|key('NumByValue',.)[1])=1]">
<xsl:copy-of select="../somenode[@key=current()]"/>
</xsl:template>
</xsl:stylesheet>
输出:
<somenode key="123" />
您能为我们提供一些示例数据吗?好问题(+1)。请参阅我的答案,了解代码中问题的解决方案和解释。谢谢!我以为表达式“/”总是允许我访问xml文档的根节点,但不知道使用临时树可以改变这种行为。@xor\U eq:/
正在选择当前文档的根节点。当前文档由
创建为临时树,因此/
正在选择临时树的根节点。看起来有点像过滤唯一元素的muenchian方法。但我这里的问题是(这就是为什么我要使用扩展方法)我必须计算节点,然后从中提取节点。正因为如此,我不能使用xsl:key,因为这是一个顶级元素。@xor_eq:我在颠倒你的逻辑。不是用所有的num
元素转换成key
元素来构建一个RTF,然后将这个RTF转换成一个节点集,对那些具有唯一字符串值的元素进行迭代,最后用这样的@key
输出所有somenode
元素。因为源代码中有唯一的值,所以不需要两步过程。为了提高性能(避免节点集比较),您可以使用另一个键匹配somenode
元素,并使用@key
@Alejandro:您完全正确,但是,在这个问题中,我编写了一个非常简单的示例。正如我现在看到的,这个例子也很糟糕,因为我没有明确说明那些num
值不必是唯一的。在我的原始代码中,我的源代码中没有唯一的值,这更像是我已经将每个num
元素提取了几百次,所以我必须首先提取唯一的值。@xor\U eq:您写道:我已经将每个num元素提取了几百次,所以我必须首先提取唯一的值。对这就是我按值对num
进行分组的原因。@Alejandro:是的,但是在xsl:key的帮助下。我不能使用这个元素,因为那些num
元素不在源代码中(这只是我的示例中的情况),它们是计算出来的。我不妨先创建另一个xml文档,它在需要之前计算所有num
元素,然后使用xsl:key进行分组,依此类推。。。但那样我就不会问了。我宁愿不必创建另一个xml文档,也不必动态计算所需的值。这使得我需要使用ext.函数,因为递归版本(我也尝试过)会在一定的复杂度下消亡