Reputation: 85
My XML.
<a>
<range nr="1" no-range="1 2 3 4" oc="4"/>
<range nr="2" no-range="41 42 43 44" oc="4"/>
<range nr="3" no-range="43 44 45 46" oc="4"/>
<range nr="4" no-range="50 51 52 53" oc="4"/>
<range nr="5" no-range="53 54" oc="2"/>
<range nr="6" no-range="60 61" oc="2"/>
</a>
I was trying this but not sure how to compare two arrays and print the difference:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:template match="a">
<xsl:variable name="bRannge">
<xsl:for-each select="range">
<xsl:variable name="aRange" select="tokenize(concat(@no-range, ' '), ' ')"/>
<xsl:value-of select="$aRange"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="cRange" select="tokenize(normalize-space($bRannge), ' ')"/>
<xsl:variable name="aSeq">
<xsl:for-each select="1 to xs:integer(number($cRange[last()]))">
<xsl:value-of select="position()"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="bSeq" select="tokenize(normalize-space($aSeq), ' ')"/>
[<xsl:value-of select="$cRange"/>]
[<xsl:value-of select="$bSeq"/>]
<!-- How to compare two arrays -->
</xsl:template>
How can I get following report using xslt 2.0:
Upvotes: 1
Views: 367
Reputation: 167706
You can create each sequence you have with a single expression and then compare them as follows:
<xsl:template match="a">
<xsl:variable name="seq1" as="xs:integer*"
select="for $s in range/@no-range/tokenize(., '\s+')
return xs:integer($s)"/>
<xsl:variable name="seq2" as="xs:integer*"
select="1 to $seq1[last()]"/>
[<xsl:value-of select="$seq1"/>]
[<xsl:value-of select="$seq2"/>]
[<xsl:value-of select="$seq2[not(. = $seq1)]"/>]
</xsl:template>
That outputs the sequence of integers not in your no-range
attribute values:
[5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 47 48 49 55 56 57 58 59]
As for finding consecutive ranges, one way would be to use grouping as follows:
<xsl:template match="a">
<xsl:variable name="seq1" as="xs:integer*"
select="for $s in range/@no-range/tokenize(., '\s+')
return xs:integer($s)"/>
<xsl:variable name="seq2" as="xs:integer*"
select="1 to $seq1[last()]"/>
[<xsl:value-of select="$seq1"/>]
[<xsl:value-of select="$seq2"/>]
<xsl:variable name="seq3" as="xs:integer*"
select="$seq2[not(. = $seq1)]"/>
[<xsl:value-of select="$seq3"/>]
<xsl:for-each-group select="$seq3" group-adjacent=". - position()">
[<xsl:value-of select="current-group()[1], current-group()[last()]"
separator=" - "/>]
</xsl:for-each-group>
which then gives
[5 - 40]
[47 - 49]
[55 - 59]
Upvotes: 3