RE: [xsl] range creation

Subject: RE: [xsl] range creation
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Sat, 19 Nov 2011 09:51:49 -0500
At 2011-11-19 19:45 +0530, Joga Singh Rawat wrote:
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.

No, I cannot. I was trying to explain that your approach to the problem was inappropriate and that a different wholistic approach is necessary.


Your "travel a distance" in your XSLT is following a lengthy chain of XSLT 1.0 constructs in an XSLT 2.0 environment. Yet XSLT 2.0 offers constructs that allow you to solve the entire problem very succinctly using groups, and you didn't take advantage of them.

I've shown you a complete solution using a robust and concise approach. Your requirement is straightforward in XSLT 2.0 as I've shown. I think your first attempt at an XSLT 1.0-oriented solution illustrates that it is not very straightforward without taking advantage of XSLT 2.0 instructions.

I felt the principles exhibited in my solution would be of interest to readers of the archive who might have similar grouping problems. Since grouping is new in XSLT 2.0, solving real-world problems should be helpful.

The use of the "inverted" test in the group-starting-with= is, I think, an interesting example of how to create groups of like constructs from a stream.

I've posted a different solution below that uses group-adjacent= for the same purpose, and in retrospect I think group-adjacent= is a better way to go for this solution. For a sequence of adjacent constructs, this is better than using group-starting-with= as I did in my first solution. Nevertheless, comparing the two is interesting.

But I do not have the volunteer time to rework your XSLT 1.0-oriented solution.

I anticipated your need to have hooks in order to accomplish what you need. I tried to document everything you would be able to work with.

Good luck in your project.

If other readers of the archive have any questions about the two approaches I've taken in my solutions, I'll be pleased to respond to any public posts in that regard.

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

<?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 joga2.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 joga2.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-->
<!--grouping those that are adjacent link constructs-->
<xsl:for-each-group select="node()" group-adjacent="boolean(self::w:link)">
<xsl:choose>
<xsl:when test="self::w:link">
<!--everything in this group is a link-->
<!--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()/@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:when>
<xsl:otherwise>
<!--nothing in this group is a link-->
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</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