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(_at_)CraneSoftwrights(_dot_)com
Google+ profile: https://plus.google.com/116832879756988317389/about
Legal business disclaimers: http://www.CraneSoftwrights.com/legal
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--