Howie
Howie

Reputation: 2778

Returning a range of elements between two siblings

So, I have this XML:

<datafield tag="610">
    <subfield code="z">eng</subfield>
    <subfield code="a">zinc</subfield>
    <subfield code="a">speciation</subfield>
    <subfield code="a">pumpkin seeds</subfield>
    <subfield code="b">iceberg lettuce</subfield>
    <subfield code="a">size exclusion chromatography</subfield>
    <subfield code="a">element-specific detection</subfield>
    <subfield code="a">physiologically based extraction test</subfield>
</datafield>

and I need to get all the code="a" elements between <subfield code="z">eng</subfield> and <subfield code="b">iceberg lettuce</subfield>. Then, I need to get all the code="a" elements after <subfield code="b">iceberg lettuce</subfield>.

My current code:

<First>                        
    <xsl:for-each select="datafield[@tag=610]/subfield[@code='a']">
        <xsl:value-of select="." />
        <xsl:text> 
        </xsl:text>
    </xsl:for-each>                    
</First>                        
<Second>                        
    <xsl:for-each select="datafield[@tag=610]/subfield[@code='a']">
        <xsl:value-of select="." />
        <xsl:text> 
        </xsl:text>
    </xsl:for-each>                    
</Second>         

I haven't found any XLST commands where I could define a range of the for-each loop, and I'm not sure if it's even possible to achieve this in pure XSLT.

That's why I'm here. I prefer solutions in XSLT 1.0, but any will do really.

Upvotes: 1

Views: 54

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 117073

In XSLT 1.0, you can do:

<xsl:template match="datafield[@tag=610]">
    <First>    
        <xsl:apply-templates select="subfield[@code='z']/following-sibling::subfield[@code='a'][following-sibling::subfield[@code='b']]"/>                    
    </First>                        
    <Second>                        
        <xsl:apply-templates select="subfield[@code='b']/following-sibling::subfield[@code='a']"/>                    
    </Second>
</xsl:template>

<xsl:template match="subfield">
    <xsl:value-of select="."/>
    <xsl:text>&#10;</xsl:text>
</xsl:template>

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167706

With XSLT/XPath 2.0 the path expression /datafield[@tag = 610]/subfield[@code = 'z']/following-sibling::subfield[@code = 'a' and . << ../subfield[@code = 'b']] would give you the elements

<subfield code="a">zinc</subfield>
<subfield code="a">speciation</subfield>
<subfield code="a">pumpkin seeds</subfield>

Note that inside of XSLT you need to escape the << operator as &lt;&lt;.

The second set is easier to access, you simply need /datafield[@tag = 610]/subfield[@code = 'b']/following-sibling::subfield[@code = 'a'].

Upvotes: 1

Related Questions