RE: [xsl] range creation

Subject: RE: [xsl] range creation
From: "Joga Singh Rawat" <jrawat@xxxxxxxxxxxxxx>
Date: Sat, 19 Nov 2011 19:45:32 +0530
HI Kin,

Thanks for your effort. Thank you very much. Problem we us is that we have
travel a distance by where everything is ok but not getting <link
href="#bib40 #bib41 #bib42 #bib45 #bib40 #bib41 #bib45"/>

The problem is in the following area within "process-bib-links" template.

        <xsl:when test="node()">
?????????
          <!--Aptara: process <link href="#c1-bib-0013 #c1-bib-0014"/> type
of -->
          <xsl:text> </xsl:text>
          <xsl:copy-of select="he:get-bib-number(.)" />
          <!-- <xsl:apply-templates /> -->
        </xsl:when>

 Can you give me a quick idea how to problem from here. 

Thanks
...JSR


-----Original Message-----
From: G. Ken Holman [mailto:gkholman@xxxxxxxxxxxxxxxxxxxx] 
Sent: Saturday, November 19, 2011 7:21 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx; xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] range creation

At 2011-11-19 14:55 +0530, Joga Singh Rawat wrote:
>Hi guys,
>My input is <link href="#bib40 #bib41 #bib42 #bib45 #bib40 #bib41 #bib45"/>
>and <link href="#bib40"/><link href="#bib41"/><link href="#bib42"/><link
>href="#bib45"/><link href="#bib40"/><link href="#bib41"/><link
>href="#bib45"/> and I want create a range of numbers, if any three numbers
>are in sequence as displayed in "Required output".
>
>Any clue is appreciated.
>
>Required Output
><a href="#bib40">1</a><a href="#bib41">2</a><a href="#bib42">3</a><a
>href="#bib45">6</a><a href="#bib40">1</a><a href="#bib41">2</a><a
>href="#bib45">6</a>.
>Should be
><a href="#bib40">1</a>--<a href="#bib42">3</a>, <a href="#bib45">6</a>, <a
>href="#bib40"> 1</a>, <a href="#bib41"> 2</a>, <a href="#bib45"> 6</a>.

Since you are using XSLT 2.0, group-starting-with= is your friend!

Below is a heavily-commented solution.  In fact the number of 
instructions when using <xsl:for-each-group> is quite small compared 
to the code you posted because I'm letting the processor do the heavy 
lifting.  I focused only on the link grouping logic and I'll leave it 
with you to decorate your links as you want.

You didn't say what to do with a hybrid collection of links, such as:

    <p>Range test: <link href="#bib40 #bib41"/><link
href="#bib42"/><link href="#bib45"/><link href="#bib40"/><link
href="#bib41"/><link href="#bib45"/>.

... so I assumed this should also be: 1-3, 6, 1, 2, 6.

The solution involves first finding all of the link elements in a 
sequence, then distilling all of the individual links into a new 
sequence, acting on groups found in that new sequence, and then 
repositioning back into the source node tree for each member of the 
sequence being acted on.

I'm also assuming the range determination is based on the sequence 
number of the link in the bibliography.  If this isn't the case, I've 
commented where in the distillation you calculate that on which you 
base your range sequencing.

I think this approach is quite robust ... I hope it helps.

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

~/t/ftemp $ cat joga.xml
<?xml version="1.0" encoding="UTF-8"?>
<component xmlns="http://www.wiley.com/namespaces/wiley";>
    <p>Range test: <link href="#bib40 #bib41 #bib42 #bib45 #bib40 #bib41
#bib45"/>. This should be 1-3, 6, 1, 2, 6.</p>
    <p>Range Test: <link href="#bib40"/><link href="#bib41"/><link
href="#bib42"/><link href="#bib45"/><link href="#bib40"/><link
href="#bib41"/><link href="#bib45"/>. This should be 1-3, 6, 1, 2, 6.</p>
    <p>Individual test: <link href="#bib40"/>, <link href="#bib41"/>, <link
href="#bib45"/>.</p>
    <p>Range test: <link href="#bib40 #bib41"/><link
href="#bib42"/><link href="#bib45"/><link href="#bib40"/><link
href="#bib41"/><link href="#bib45"/>. Should this be 1-3, 6, 1, 2, 6?</p>
    <bibliography style="numbered">
     <bib xml:id="bib40">bib1</bib>
     <bib xml:id="bib41">bib2</bib>
     <bib xml:id="bib42">bib3</bib>
     <bib xml:id="bib43">bib4</bib>
     <bib xml:id="bib44">bib5</bib>
     <bib xml:id="bib45">bib6</bib>
    </bibliography>
</component>
~/t/ftemp $
~/t/ftemp $ xslt2 joga.xml joga.xsl
<html>
    <head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
       <title>Link test</title>
    </head>
    <body>

       <p>Range test: <a href="#bib40">1</a>-<a href="#bib42">3</a>, 
<a href="#bib45">6</a>, <a href="#bib40">1</a>, <a 
href="#bib41">2</a>, <a href="#bib45">6</a>. This should be 1-3, 6, 1, 2, 6.
       </p>

       <p>Range Test: <a href="#bib40">1</a>-<a href="#bib42">3</a>, 
<a href="#bib45">6</a>, <a href="#bib40">1</a>, <a 
href="#bib41">2</a>, <a href="#bib45">6</a>. This should be 1-3, 6, 1, 2, 6.
       </p>

       <p>Individual test: <a href="#bib40">1</a>, <a 
href="#bib41">2</a>, <a href="#bib45">6</a>.
       </p>

       <p>Range test: <a href="#bib40">1</a>-<a href="#bib42">3</a>, 
<a href="#bib45">6</a>, <a href="#bib40">1</a>, <a 
href="#bib41">2</a>, <a href="#bib45">6</a>. Should this be 1-3, 6, 1, 2, 6?
       </p>

       <ol>
          <p name="bib40">bib1</p>
          <p name="bib41">bib2</p>
          <p name="bib42">bib3</p>
          <p name="bib43">bib4</p>
          <p name="bib44">bib5</p>
          <p name="bib45">bib6</p>
       </ol>

    </body>
</html>~/t/ftemp $
~/t/ftemp $ cat joga.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                 xmlns:w="http://www.wiley.com/namespaces/wiley";
                 exclude-result-prefixes="w"
                 version="2.0">

<xsl:template match="w:component">
   <html>
     <head><title>Link test</title></head>
     <body><xsl:apply-templates/></body>
   </html>
</xsl:template>

<xsl:variable name="doc" select="/"/>

<xsl:template match="w:p">
   <p>
     <!--act on sequences of links-->
     <!--by grouping starting with those that are not links, those in 
a sequence
         of links end up all in one group-->
     <xsl:for-each-group select="node()"
                         group-starting-with="node()[not(self::w:link)]">
       <!--process everything in the group that isn't a link-->
       <xsl:apply-templates select="current-group()[not(self::w:link)]"/>
       <!--process everything in the group that is a link (all are at
end)-->
       <!--next present the ranged list of bibliographic references-->
       <!--distill all link information in specified order of singletons-->
       <xsl:variable name="links">
         <xsl:for-each
 
select="current-group()[self::w:link]/@href/tokenize(.,'(\s+|#)')[.]">
           <xsl:for-each select="id(.,$doc)">
             <distilled-link idref="{@xml:id}">
               <!--the bibliographic sequence number -->
               <xsl:value-of select="count(preceding-sibling::*
                                     [node-name(.)=node-name(current())]) 
+ 1"/>
             </distilled-link>
           </xsl:for-each>
         </xsl:for-each>
       </xsl:variable>
       <!--group all singleton links based on sequences of two or more-->
       <!--by grouping staring with those not in a sequence, those in 
a sequence
           end up all in one group-->
       <xsl:for-each-group select="$links/distilled-link"
                     group-starting-with="distilled-link
                                          [. !=
(preceding-sibling::*[1]+1)]">
         <xsl:choose>
           <xsl:when test="count(current-group())>2">
             <!--found a range of sequential links-->
             <xsl:apply-templates select="."/>
             <xsl:text>-</xsl:text>
             <xsl:apply-templates select="current-group()[last()]"/>
           </xsl:when>
           <xsl:otherwise>
             <!--found a standalone or a pair of links-->
             <xsl:for-each select="current-group()">
               <xsl:if test="position()>1">, </xsl:if>
               <xsl:apply-templates select="."/>
             </xsl:for-each>
           </xsl:otherwise>
         </xsl:choose>
         <!--add a delimiter; assume terminator supplied in the source-->
         <xsl:if test="position()!=last()">, </xsl:if>
       </xsl:for-each-group>
     </xsl:for-each-group>
   </p>
</xsl:template>

<xsl:template match="distilled-link">
   <xsl:for-each select="id(@idref,$doc)">
     <!--now positioned at the bibliographic reference ready for
processing-->
     <a href="#{@xml:id}"><xsl:number/></a>
   </xsl:for-each>
</xsl:template>

<xsl:template match="w:bibliography">
   <ol>
     <xsl:for-each select="w:bib">
       <p name="{@xml:id}"><xsl:apply-templates/></p>
     </xsl:for-each>
   </ol>
</xsl:template>

</xsl:stylesheet>~/t/ftemp $
~/t/ftemp $


--
Contact us for world-wide XML consulting and instructor-led training
Free 5-hour video lecture: XSLT/XPath 1.0 & 2.0 http://ude.my/t37DVX
Crane Softwrights Ltd.            http://www.CraneSoftwrights.com/s/
G. Ken Holman                   mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Google+ profile: https://plus.google.com/116832879756988317389/about
Legal business disclaimers:    http://www.CraneSoftwrights.com/legal

Current Thread