Re: [xsl] multiple range expansion

Subject: Re: [xsl] multiple range expansion
From: Ganesh Babu N <nbabuganesh@xxxxxxxxx>
Date: Tue, 23 Jun 2009 11:22:18 +0530
Thanks Ken,

I got the concept and converted successfully. Instead of for-each i
have used for to get spaces between ids. But one place i am unable to
remove. Please help to achieve this.

Input:

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

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

Output from modified XSL:
<cross-refs refid="bib5 bib6 bib7bib21 bib22 bib23 bib24">[5-7,
21-24]</cross-refs>

Modified XSL code:
<xsl:analyze-string select="." regex="(\d+)(\s*-\s*(\d+))?">
  <xsl:matching-substring>
     <xsl:value-of select="for $i in xs:integer(regex-group(1)) to
(if(regex-group(3)) then xs:integer(regex-group(3)) else
xs:integer(regex-group(1))) return concat('bib', $i)"/>
   </xsl:matching-substring>
</xsl:analyze-string>

Please suggest. bib7 and bib21 has to be separated.

Regards,
Ganesh


On Mon, Jun 22, 2009 at 5:46 PM, G. Ken
Holman<gkholman@xxxxxxxxxxxxxxxxxxxx> wrote:
> 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