简体   繁体   中英

using set:intersection in XSLT

I am trying to use tokenize with intersection from exslt in XALAN.

Sample Code:

<?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>

Here is sample Input:

<ROOT>
<Var1>Hello|One|Two</Var1>
<Var2>Hello|One|Two|Three</Var2>
</ROOT>

I would expect intersection to report value of 3 - but it is always reporting 0.

My current output:

<?xml version="1.0" encoding="UTF-8"?>
    Number of Values in Var1: 3
    Number of Values in Var2: 4
    Common Values: 0

Is there something incorrect in approach?

Yes the two calls to str:tokenize yield two distinct sets of token elements. None of the nodes in the first set are present in the second set. The two nodesets contain element nodes some of which have the same name and textual content as nodes in the other set, but in each such case these are pairs of nodes which have the same properties, but not the same node.

What you need is to define an intersection based on textual equality rather than node identity.

You could try something like this:

<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]"/>

This will return the set of nodes from $set1 which are textually equal to a node in $set2 .

Here is final solution, with Conal's solution example:

<?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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM