我正试图在XALAN中使用带有exslt交集的标记化。
样本代码:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets" xmlns:str="http://exslt.org/strings"
>
<xsl:template match="/">
Number of Values in Var1: <xsl:value-of select="count(str:tokenize(ROOT/Var1,'|'))" />
Number of Values in Var2: <xsl:value-of select="count(str:tokenize(ROOT/Var2,'|'))" />
Common Values: <xsl:value-of select="count(set:intersection(str:tokenize(ROOT/Var1,'|'),str:tokenize(ROOT/Var2,'|')))" />
</xsl:template>
</xsl:stylesheet>
这是示例输入:
<ROOT>
<Var1>Hello|One|Two</Var1>
<Var2>Hello|One|Two|Three</Var2>
</ROOT>
我希望交集报告值为3,但它总是报告0。
我的当前输出:
<?xml version="1.0" encoding="UTF-8"?>
Number of Values in Var1: 3
Number of Values in Var2: 4
Common Values: 0
方法中有什么不正确的地方吗?
是的,对str:tokenize
的两个调用产生两组不同的token
元素。第一集合中的节点都不存在于第二集合中。这两个节点集包含元素节点,其中一些节点与另一个节点集中的节点具有相同的名称和文本内容,但在每种情况下,这些节点都是具有相同属性但不是同一节点的节点对。
您需要的是基于文本相等性而不是节点标识来定义交集。
你可以试试这样的东西:
<xsl:variable name="set1" select="str:tokenize(ROOT/Var1,'|')"/>
<xsl:variable name="set2" select="str:tokenize(ROOT/Var2,'|')"/>
<xsl:variable name="intersection" select="$set1[.=$set2]"/>
这将返回来自$set1
的一组节点,这些节点在文本上等于$set2
中的一个节点。
以下是最终解决方案,Conal的解决方案示例:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets" xmlns:str="http://exslt.org/strings" xmlns:common="http://exslt.org/common"
>
<xsl:template match="/">
Number of Values in Var1: <xsl:value-of select="count(str:tokenize(ROOT/Var1,'|'))" />
Number of Values in Var2: <xsl:value-of select="count(str:tokenize(ROOT/Var2,'|'))" />
Common Values: <xsl:value-of select="count(set:intersection(str:tokenize(ROOT/Var1,'|'),str:tokenize(ROOT/Var2,'|'))/token)" />
<xsl:variable name="set1" select="str:tokenize(ROOT/Var1,'|')"/>
<xsl:variable name="set2" select="str:tokenize(ROOT/Var2,'|')"/>
<xsl:variable name="intersection" select="$set1[.=$set2]"/>
<xsl:value-of select="count($intersection)"/>
<xsl:for-each select="$intersection">
<xsl:value-of select="node()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>