[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Creating sequence/range text from position

Subject: Re: Creating sequence/range text from position
From: "Charles O'Connor coconnor@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 28 Jan 2023 16:50:50 -0000
 Re: Creating sequence/range text from position
Thanks Vincent, and great to see you at NISO meetings!

This works great! I will now spend a couple hours figuring out how you did it
(or trying to), because that's how I've learned the little XSLT that I know.

Best,
Charles

From: Lizzi, Vincent vincent.lizzi@xxxxxxxxxxxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Saturday, January 28, 2023 12:50 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject:  Re: Creating sequence/range text from position

*** External email: use caution ***

Hi Charles,

Here is a slightly improved version that produces the expected output from
your sample input and also copes with a case of the id's listed in @rid not
being in sequential order.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="3.0">

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:key name="element-by-id" match="*[@id]" use="@id"/>

    <xsl:template name="label" as="element(label)">
        <xsl:param name="id" as="xs:string"/>
        <xsl:param name="context" as="node()" select="root(.)"/>
        <label><xsl:value-of select="1 + count(key('element-by-id', $id,
$context)/preceding::ref)"></xsl:value-of></label>
    </xsl:template>

    <xsl:template match="ref">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:call-template name="label">
                <xsl:with-param name="id" select="@id"/>
            </xsl:call-template>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="xref[not(node())]">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:variable name="context" select="root(.)"/>
            <xsl:variable name="labels" as="element(label)*">
                <xsl:for-each select="tokenize(@rid)">
                    <xsl:call-template name="label">
                        <xsl:with-param name="id" select="."/>
                        <xsl:with-param name="context" select="$context"/>
                    </xsl:call-template>
                </xsl:for-each>
            </xsl:variable>
            <xsl:variable name="sorted" as="element(labels)">
                <labels>
                    <xsl:for-each select="$labels">
                        <xsl:sort select="number()"/>
                        <xsl:sequence select="."/>
                    </xsl:for-each>
                </labels>
            </xsl:variable>
            <xsl:variable name="formatted" as="xs:string*">
                <xsl:for-each select="$sorted/label">
                    <xsl:choose>
                        <xsl:when test="not(preceding::label)">
                            <xsl:sequence select="string()"/>
                        </xsl:when>
                        <xsl:when test="number() - 1 eq
number(preceding::label[1])
                            and number() + 1 eq
number(following::label[1])"/>
                        <xsl:when test="number() - 1 eq
number(preceding::label[1])
                            and number() - 2 eq number(preceding::label[2])">
                            <xsl:sequence select="'-' || string()"/>
                        </xsl:when>
                        <xsl:when test="preceding::label">
                            <xsl:sequence select="',' || string()"/>
                        </xsl:when>
                    </xsl:choose>
                </xsl:for-each>
            </xsl:variable>
            <xsl:value-of select="string-join($formatted, '')"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Best wishes,
Vincent

_____________________________________________
Vincent M. Lizzi
Head of Information Standards | Taylor & Francis Group
vincent.lizzi@xxxxxxxxxxxxxxxxxxxx<mailto:vincent.lizzi@xxxxxxxxxxxxxxxxxxxx>




Information Classification: General
From: Charles O'Connor coconnor@xxxxxxxxxxxx<mailto:coconnor@xxxxxxxxxxxx>
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx<mailto:xsl-list-service@xxxxxxxxxxxx
rytech.com>>
Sent: Friday, January 27, 2023 7:05 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx<mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Subject:  Creating sequence/range text from position

Hi all,

We use a word processor-like XML editor that presents users with generated
text for numbered bibliographic references and their in-text citations.
However, downstream systems require actual text to be placed. Question is, how
do we get it?

(Using SaxonEE 10.x)

Given

<article>
<p>Case 1 is <xref ref-type="bibr" rid="r2"/></p>
<p>Case 2 is <xref ref-type="bibr" rid="r1 r2 r3 r5 r6 r8 r9 r10"/></p>
<back>
<ref-list>
<ref id="r1">...</ref>
<ref id="r2">...</ref>
<ref id="r3">...</ref>
<ref id="r4">...</ref>
<ref id="r5">...</ref>
<ref id="r6">...</ref>
<ref id="r7">...</ref>
<ref id="r8">...</ref>
<ref id="r9">...</ref>
<ref id="r10">...</ref>
</ref-list>
</back>
</article>

We want

<article>
<p>Case 1 is <xref ref-type="bibr" rid="r2">2</xref></p>
<p>Case 2 is <xref ref-type="bibr" rid="r1 r2 r3 r5 r6 r8 r9
r10">1-3,5,6,8-10</xref></p>
<back>
<ref-list>
<ref id="r1">...</ref>
<ref id="r2">...</ref>
<ref id="r3">...</ref>
<ref id="r4">...</ref>
<ref id="r5">...</ref>
<ref id="r6">...</ref>
<ref id="r7">...</ref>
<ref id="r8">...</ref>
<ref id="r9">...</ref>
<ref id="r10">...</ref>
</ref-list>
</back>
</article>

(only the xrefs have changed)

Case 1 is pretty easily handled with:

<xsl:template match="xref[@ref-type='bibr']">
<xsl:variable name="rid" select="@rid" />
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:value-of
select="count(/article/back/ref-list/ref[@id=$rid]/preceding-sibling::ref) +
1" />
</xsl:copy>
</xsl:template>

But Case 2 is not even close. I tried adapting the solution here, to no avail:
https://stackoverflow.com/questions/47559712/xslt-sequence-of-numbers-to-rang
e

Whatever I did, I just got the first number and none of the rest. The extra
twist here is that numbers should only be expressed as a range when 3 or more
occur sequentially.

Thanks,
Charles

Charles O'Connor l Lead Product Manager
Pronouns: He/Him
Aries Systems Corporation l www.ariessys.com<http://www.ariessys.com>
50 High Street, Suite 21 l North Andover, MA l 01845 l USA


Main: +1 (978) 975-7570
Cell: +1 (802) 585-5655


XSL-List info and archive<http://www.mulberrytech.com/xsl/xsl-list>
EasyUnsubscribe<http://lists.mulberrytech.com/unsub/xsl-list/2963104> (by
email<>)

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.