[xsl] range creation

Subject: [xsl] range creation
From: "Joga Singh Rawat" <jrawat@xxxxxxxxxxxxxx>
Date: Sat, 19 Nov 2011 14:55:45 +0530
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>.

INPUT
<component>
   <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>
   <bibliography style="numbered">
    <bib xml:id="bib40"> xxx</bib>
    <bib xml:id="bib41"> xxx</bib>
    <bib xml:id="bib42"> xxx</bib>
    <bib xml:id="bib43"> xxx</bib>
    <bib xml:id="bib44"> xxx</bib>
    <bib xml:id="bib45"> xxx</bib>
   </bibliography>
</component>

XSLT
<xsl:stylesheet version="2.0"
                xmlns="http://www.w3.org/1999/xhtml";
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:xs="http://www.w3.org/2001/XMLSchema";
                xmlns:w="http://www.wiley.com/namespaces/wiley";
                xmlns:he="urn://he.wiley.com/functions/rendering"
                xmlns:saxon="http://saxon.sf.net/";
                extension-element-prefixes="saxon"
                exclude-result-prefixes="w xs he saxon">

  <xsl:output method="xhtml" />
  <xsl:template match="/">
    <html><head><title>range creation</title> </head>
      <body><xsl:apply-templates/></body>
   </html>
  </xsl:template>
  <xsl:template match="w:component">
      <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="w:p">
      <p><xsl:apply-templates/></p>
  </xsl:template>
  <xsl:template match="w:bibliography">
      <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="w:bib">
   <xsl:for-each select=".">
    <p id="{@xml:id}">
     <xsl:call-template name="handle-bib-label">
      <xsl:with-param name="bib" select="."/>
     </xsl:call-template>
     <xsl:apply-templates select="node()[not(self::w:label)]"/>
    </p>
   </xsl:for-each>
  </xsl:template>
  <xsl:template name="handle-bib-label">
    <xsl:param name="bib" as="element(w:bib)"/>
    <xsl:number select="$bib" count="w:bib[not(w:label)]"
from="w:bibliography" level="any"/>
  </xsl:template>
  <xsl:template match="w:link">
   <xsl:call-template name="process-internal-link" />
  </xsl:template>
  <xsl:template name="process-internal-link">
    <xsl:variable name="link-content">
      <xsl:apply-templates />
    </xsl:variable>
    <xsl:variable name="refs" select="@href"/>
    <xsl:variable name="single-ref">
      <xsl:choose>
        <xsl:when test="contains($refs, ' ')">
          <xsl:value-of select="substring-before($refs, ' ')" />
        </xsl:when>
        <xsl:otherwise>
         <xsl:value-of select="$refs"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <xsl:variable name="actual-refs">
      <xsl:sequence select="for $i in tokenize(concat($refs, ' '), ' ')
return if (starts-with($i, '#')) then substring-after($i, '#') else
substring-after($i, concat(unitId, ':')) " />
    </xsl:variable>
    <xsl:variable name="referenced-elements" select="for $i in
tokenize(concat($refs,' '),' ')
                        return id( if (starts-with($i, '#')) then
substring-after($i, '#')
                        else substring-after($i, concat(unitId, ':')) )" />
    <xsl:choose>
      <xsl:when test="$link-content and $link-content != '' ">
        <a>
          <xsl:attribute name="href">
            <xsl:choose>
              <xsl:when test="$single-ref !='' and $single-ref !=' '">
                <xsl:value-of select="$single-ref" />
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="$actual-refs" />
              </xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
          <xsl:attribute name="rel">
            <xsl:value-of select="concat('references:',
string-join($actual-refs, ' '))" />
          </xsl:attribute>
          <span class="link-content">
            <xsl:copy-of select="$link-content" />
          </span>
        </a>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="single-ref-test">
          <xsl:variable name="temp">
            <xsl:analyze-string select="$single-ref" regex="^[# ]*([^ ]+)
*$">
              <xsl:matching-substring>
                <xsl:value-of select="regex-group(1)"/>
              </xsl:matching-substring>
            </xsl:analyze-string>
          </xsl:variable>
          <xsl:analyze-string select="$temp" regex="^.*:([^ ]+)$">
            <xsl:matching-substring>
              <xsl:value-of select="regex-group(1)"/>
            </xsl:matching-substring>
            <xsl:non-matching-substring>
              <xsl:value-of select="$temp"/>
            </xsl:non-matching-substring>
          </xsl:analyze-string>
          <xsl:text> </xsl:text>
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="$single-ref-test eq $actual-refs">
            <xsl:call-template name="enumerated-single-link">
              <xsl:with-param name ="referenced-element"
select="$referenced-elements"/>
              <xsl:with-param name ="actual-ref" select="$actual-refs"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="enumerated-multiple-links">
              <xsl:with-param name ="referenced-elements"
select="$referenced-elements"/>
              <xsl:with-param name ="actual-refs" select="$actual-refs"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  <xsl:template name="enumerated-single-link">
    <xsl:param name="referenced-element"/>
    <xsl:param name="actual-ref"/>
    <xsl:choose>
      <xsl:when test="$referenced-element/self::w:bib">
        <xsl:call-template name="process-bib-links">
          <xsl:with-param name="element" select="$referenced-element" />
          <xsl:with-param name="actual-ref" select="$actual-ref" />
        </xsl:call-template>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
  <xsl:template name="enumerated-multiple-links">
    <xsl:param name="referenced-elements"/>
    <xsl:param name="actual-refs"/>
    <xsl:variable name="sequence-refs" select="tokenize($actual-refs,'[
]+')"/>
    <xsl:for-each select="$referenced-elements">
      <xsl:variable name="curr-pos" select="position()"/>
      <xsl:call-template name="enumerated-single-link">
        <xsl:with-param name ="referenced-element"
select="$referenced-elements[position()=$curr-pos]"/>
        <xsl:with-param name ="actual-ref"
select="$sequence-refs[position()=$curr-pos]"/>
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>
  <xsl:template name="process-bib-links">
    <xsl:param name="element" />
    <xsl:param name="actual-ref" />
    <a href="#{$actual-ref}">
      <xsl:choose>
        <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>
        <xsl:otherwise>
          <xsl:for-each select="$element">
            <xsl:if test="position() &gt; 1">
              <xsl:text>, </xsl:text>
            </xsl:if>
            <xsl:copy-of select="he:get-bib-number(.)" />
          </xsl:for-each>
        </xsl:otherwise>
      </xsl:choose>
    </a>
  </xsl:template>
  <xsl:function name="he:get-bib-number" as="item()*">
    <xsl:param name="bib" as="element(w:bib)"/>
    <xsl:call-template name="handle-bib-label">
      <xsl:with-param name="bib" select="$bib"/>
    </xsl:call-template>
  </xsl:function>

</xsl:stylesheet>

Thanks
...JSR

Current Thread