Re: [xsl] multiple range expansion

Subject: Re: [xsl] multiple range expansion
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Mon, 22 Jun 2009 08:16:38 -0400
At 2009-06-22 14:11 +0530, Ganesh Babu N wrote:
I am having the following inputs:

1. <cross-ref>[<cr refid="MEP_L_bib5">5</cr>-<cr
refid="MEP_L_bib7">7</cr>, <cr refid="MEP_L_bib21">21</cr>-<cr
refid="MEP_L_bib24">24</cr>]</cross-ref>

2. <cross-ref>[<cr refid="MEP_L_bib2">2</cr>,<cr
refid="MEP_L_bib4">4</cr>]</cross-ref>

3. <cross-ref>[<cr refid="MEP_L_bib5">5</cr>-<cr
refid="MEP_L_bib7">7</cr>]</cross-ref>

the required output is as follows:

1. <cross-refs refid="bib5 bib6 bib7 bib21 bib22 bib23 bib24">[5-7,
21-24]</cross-refs>

2. <cross-refs refid="bib2 bib4">[2, 4]</cross-refs>

3. <cross-refs refid="bib5 bib6 bib7">[5-7]</cross-refs>

I have tried this with the following code:

<xsl:template match="cross-ref">
<xsl:choose>
<xsl:when test="contains(.,'-')">
   <ce:cross-refs>
     <xsl:attribute name="refid">
         <xsl:if test="cr/@refid[contains(., 'bib')]">
              <xsl:variable name="start"
select="cr[following-sibling::text()[1] =
'-']/@refid/xs:integer(substring-after(.,'MEP_L_bib'))"/>

Your variable's value is not a singleton ... you will get as many start points as you have ranges. You are not working through your value in a piecemeal manner handling one range at a time.


When I execute the above code i am getting the following error:

  XPTY0004: A sequence of more than one item is not allowed as the
first operand of 'to' (5, 21)

Right ... because the sibling axis is grabbing all starts of ranges.


I have tried with

<xsl:for-each select="$start and $end">
<xsl:value-of select="for $i in $start to $end return concat('bib', $i)"/>
</xsl:for-each>


Even this also not working.

Now you are just guessing instead of considering the root of your problem of not working with singleton values. The error message was clear, yet you are still trying to work with the improperly-structured first operand. Moreover, the "and" operator is a boolean operator, thus "$start and $end" is a boolean value of true/false and since both operands are non-zero numbers or non-empty strings, the value will always be true.


In the code below, I am using <xsl:analyze-string> to give me an opportunity to work with each of the page ranges one at a time. I am making the assumption that the #PCDATA text matches the attribute values, thus I can do the work without looking inside of the attributes.

Note that with <xsl:analyze-string> one gets the opportunity to describe a match pattern where each range is dealt with one at a time, thus the "to" operator can work with singleton operands.

I hope this helps.

. . . . . . . . . . . Ken

T:\ftemp>type ganesh.xml
<tests>
1. <cross-ref>[<cr refid="MEP_L_bib5">5</cr>-<cr
refid="MEP_L_bib7">7</cr>, <cr refid="MEP_L_bib21">21</cr>-<cr
refid="MEP_L_bib24">24</cr>]</cross-ref>

2. <cross-ref>[<cr refid="MEP_L_bib2">2</cr>,<cr
refid="MEP_L_bib4">4</cr>]</cross-ref>

3. <cross-ref>[<cr refid="MEP_L_bib5">5</cr>-<cr
refid="MEP_L_bib7">7</cr>]</cross-ref>
</tests>
T:\ftemp>call xslt2 ganesh.xml ganesh.xsl
<?xml version="1.0" encoding="UTF-8"?>
<tests>
1. <cross-refs refid="bib5 bib6 bib7 bib21 bib22 bib23 bib24 ">[5-7, 21-24]</cross-refs>


2. <cross-refs refid="bib2 bib4 ">[2,4]</cross-refs>

3. <cross-refs refid="bib5 bib6 bib7 ">[5-7]</cross-refs>
</tests>
T:\ftemp>type ganesh.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:xsd="http://www.w3.org/2001/XMLSchema";
                exclude-result-prefixes="xsd"
                version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="cross-ref">
<cross-refs>
<xsl:attribute name="refid">
<xsl:analyze-string select="." regex="(\d+)(\s*-\s*(\d+))?">
<xsl:matching-substring>
<xsl:for-each select="xsd:integer(regex-group(1)) to
(if(regex-group(3)) then xsd:integer(regex-group(3))
else xsd:integer(regex-group(1)))">
<xsl:value-of select="concat('bib',.,' ')"/>
</xsl:for-each>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:attribute>
<xsl:value-of select="."/>
</cross-refs>
</xsl:template>


<xsl:template match="@*|node()"><!--identity for all other nodes-->
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
T:\ftemp>rem Done!



--
Crane Softwrights Ltd.          http://www.CraneSoftwrights.com/s/
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video lesson:    http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18
Video overview:  http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18
G. Ken Holman                 mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Male Cancer Awareness Nov'07  http://www.CraneSoftwrights.com/s/bc
Legal business disclaimers:  http://www.CraneSoftwrights.com/legal

Current Thread