mark1234 February 2016

Get a nodeset that contains values from another nodeset XSLT1.0

I'm using XSLT1.0 and can't use any extensions. I have a node set and need to find all the elements in another node set that contain the values in the first and list them as related nodes.

The example below is a bit contrived, as the XML I'm working with is very large and contains confidential data so I made up some data.

In example in the following XML I am processing the sets. When I get to set_no 1 I find out that there are sub-sets 1,2 & 3. I then need to find and list in sub_sec order, all the book/chapter/section/sub_section/sub_sec elements, whose sec_no is in 1,2,3 (sets/set1/sub_set values)

So my result should be:

set1 
A
B
C
D
E
F
G

set2
A
B
C
D
G 

In SQL, it would be an IN clause

    <?xml version="1.0" encoding="UTF-8"?>
<root>
    <sets>
        <set>
            <set_no>1</set_no>
            <sub_sets>
                <sub_set>1</sub_set>
                <sub_set>2</sub_set>
                <sub_set>3</sub_set>
            </sub_sets>
        </set>
        <set>
            <set_no>2</set_no>
            <sub_sets>
                <sub_set>1</sub_set>
                <sub_set>3</sub_set>
            </sub_sets>
        </set>
    </sets>
    <book>
        <chapter>
            <section>
                <sec_no>1</sec_no>
                <sub_section>
                    <sub_sec>A</sub_sec>
                    <sub_sec>B</sub_sec>
                    <sub_sec>C</sub_sec>
                    <sub_sec>D</sub_sec>
                    <sub_sec>G</sub_sec>
                </sub_section>
            </section>
            <section>
                <sec_no>2</sec_no>
                <sub        

Answers


Matthew February 2016

This should work:

<xsl:template match="root">
    <html>
        <body>
            <xsl:for-each select="sets/set">
                Set: <xsl:value-of select="set_no"/>
                <br/>
                <xsl:for-each select="/root/book/chapter/section[sec_no=current()/sub_sets/sub_set]/sub_section/sub_sec">
                    <xsl:sort select="."/>
                    <xsl:value-of select="."/><br />                    
                </xsl:for-each>
            </xsl:for-each>
        </body>
    </html>
</xsl:template>

This produces:

Set: 1<br>A<br>B<br>C<br>D<br>E<br>F<br>G<br>
Set: 2<br>A<br>B<br>C<br>D<br>G<br>

where the output is ordered as you requested.

In the predicate expression [sec_no=current()/sub_sets/sub_set], current() is bound to the set being evaluated, and therefore current()/sub_sets/sub_set gets the list of sub_set values in the current set. The predicate will be true when the sec_no is in this list.


michael.hor257k February 2016

This type of problem is best solved using a key:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="sub_sec-by-sec_no" match="sub_sec" use="ancestor::section/sec_no" />

<xsl:template match="/root">
    <html>
        <body>
            <xsl:for-each select="sets/set">
                Set: <xsl:value-of select="set_no"/>
                <br/>
                <xsl:for-each select="key('sub_sec-by-sec_no', sub_sets/sub_set)">
                    <xsl:sort select="." data-type="text" order="ascending"/>
                    <xsl:value-of select="."/>
                    <br/>
                </xsl:for-each>
                <br/><br/>
            </xsl:for-each>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>

Post Status

Asked in February 2016
Viewed 3,264 times
Voted 9
Answered 2 times

Search




Leave an answer