Home > Software engineering >  XSLT 3.0: Using a accumulator , how to accumulator values and break a line between them And how to r
XSLT 3.0: Using a accumulator , how to accumulator values and break a line between them And how to r

Time:06-09

I have xml (described below) with footnotes (described 'note' tag ), which I want to turn into a -html document divided into pages, where up to the 'eop' tag accumulate 'note' tags in the accumulator 'notes' and then pull out all the 'note' tags that have accumulated so far and display them and close the page. Go to the next page and so on. Each individual footnote should be in a separate line, To do this you have to wrap each individual footnote in the div tag (which I could not do) or alternatively move to the next line before each new footnote (what you see in xslt below but does not work)

And another thing I need is to reset the occulator as soon as there is an eop. I added (<xsl: accumulator-rule match = "eop" select = "''" />) but it over before showing The following xslt describes what I did and does not do what is required Can someone help me?

xml:

<?xml version="1.0" encoding="UTF-8"?>
<dataRoot>
    <article>
        <point>
            <p>aaa</p>
            <note marker="*" >note 1</note>
            <p>bbb
                <eop>100</eop>
            </p>
            <p>ccc
                <note marker="*">note 2</note>
            </p>
        </point>
        <point>
            <note marker="**">note 3</note>
            <p>ddd</p>
            <p>eee</p>
        </point>
        <point>
            <note marker="***">note 4</note>
        </point>
        <eop>101</eop>
    </article>
    <article>
        <note marker="*">note 5</note>
        <point>
            <p>fff</p>
            <p>ggg
                <eop>102</eop>
            </p>
        </point>
        <point>
            <note marker="*">note 6</note>
        </point>
    </article>
</dataRoot>

xslt:

<?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 use-accumulators="#all" streamable="no"/>
    <xsl:output omit-xml-declaration="no" indent="yes"/>
    <xsl:accumulator name="notes" initial-value="''">
        <xsl:accumulator-rule match="note" select="concat($value,'&#10;',@marker,.)"/>
    </xsl:accumulator>
    <xsl:template match="/">
        <html>
            <head>
                <style type="text/css">
                 
                </style>
            </head>
            <body>
                <xsl:apply-templates />
            </body>
        </html>
    </xsl:template>
    <xsl:template match="eop">
        <div >
            -- </div>
        <div >
            <xsl:value-of select="accumulator-before('notes')"/>
        </div>
        <div >
            <xsl:value-of select='.' />
        </div>
        <div >
            ------------ </div>
    </xsl:template>
    <xsl:template match="article" >
        <xsl:apply-templates />
    </xsl:template>
    <xsl:template match="point" >
        <div >
            <xsl:value-of select="text()"></xsl:value-of>
            <xsl:apply-templates />
        </div>
    </xsl:template>
    <xsl:template match="p" >
        <xsl:apply-templates />
    </xsl:template>
    <xsl:template match="note" >
        <span >
            <xsl:value-of select="@marker"/>
        </span>
    </xsl:template>
</xsl:stylesheet>

output html:

aaa * bbb
--
*note 1
100
------------
ccc *
** ddd eee
***
--
*note 1 *note 2 **note 3 ***note 4
101
------------
*
fff ggg
--
*note 1 *note 2 **note 3 ***note 4 *note 5
102
------------
*

CodePudding user response:

I am not sure I do understand

And another thing I need is to reset the occulator as soon as there is an eop. I added (<xsl:accumulator-rule match = "eop" select = "''" />) but it over before showing

if you want to reset when encountering an eop that code should be right; as you, however, try to read out the value when matching on eop I supposed you rather want to reset with <xsl:accumulator-rule match = "eop" select = "''" phase="end"/>.

As for inserting line break, perhaps don't collect a single string value as the accumulator value but a sequence of strings e.g.

<xsl:accumulator name="notes" as="xs:string*" initial-value="()">
    <xsl:accumulator-rule match="note" select="$value, @marker || ."/>
    <xsl:accumulator-rule match="eop" select="()" phase="end"/>
</xsl:accumulator>

then, accumulator-before('notes') gives you a sequence of string you can process with xsl:iterate or xsl:for-each or xsl:apply-templates to wrap in adequate markup (e.g. div or ul/li or with br) inserted.

  • Related