XSLT: Problem merging following elements

Here should go questions about transforming XML with XSLT and FOP.
boater
Posts: 11

XSLT: Problem merging following elements

Mon Oct 26, 2015 5:58 pm

I'm transforming legacy plain text into XML.

I have text at this point:

Code: Select all

         <notes>
            <p> 1 Serve coffee within 30 minutes.</p>
            <p> 2 Check water temperature. The water filtered through the grounds must be 200 F. to ensure that the coffee from the brewing chamber</p>
            <p>   will be at least 190 F.</p>
            <p> 3 For 1 pot: Use 2-1/2 ounces or 3/4 cup roasted, ground coffee. One pot makes 11 5-ounce portions or 7 8-ounce portions.</p>
            <p> 4 Coffee Maker Production Rates: 2 to 3 minutes to reach water temperature.</p>
            <p>   minutes average brewing time. </p>
            <p>   1 pot in average of 7 minutes. 8 pots per hour.</p>
            <p>   The end of line 4.</p>
            <p> 5 For 5-ounce portions: In Step 1, use 1-1/2 pound or 1-7/8 quarts roasted, ground coffee to make 10 pots.</p>
            <p> 6 For stronger brew, use 2-13/16 pounds or 3-1/2 quarts roasted, ground coffee for 8-ounce portion; for 5-ounce portion, use 2 pounds or</p>
            <p>   2-1/2 quarts roasted, ground coffee.</p>
         </notes>


I'm trying to merge lines. Specifically, I want to take the continuation lines (they start with a leading 3 blank spaces) and append them to the line above it. I exaggerated the continuation lines for line (4) to illustrate.

I thought I have this xsl close. But it hasn't worked.

Code: Select all

<?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="2.0">
   
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*"/>
   
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
   
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
   
    <!-- remove the continuation lines, we'll merge them in a different template -->
    <xsl:template match="p[starts-with( . ,'   ')]"/>
   
    <!-- these are the true new lines, we'll append the continuation text to this text -->
    <xsl:template match="p[not(starts-with( . ,'   '))]">
        <p>
            <xsl:copy-of select="text()"/>
            <xsl:call-template name="append-continuation-lines"/>
        </p>
    </xsl:template>
   
    <!-- flawed xpath in for-each: get following continuation lines, before the next real line -->
    <xsl:template name="append-continuation-lines">
        <xsl:for-each select="
            following::p[starts-with( . ,'   ')]
            [following::p[not(starts-with( . ,'   '))]]">
            <xsl:copy-of select="text()"/>
        </xsl:for-each>
    </xsl:template>
   
</xsl:stylesheet>


Any ideas?
boater
Posts: 11

Re: XSLT: Problem merging following elements

Tue Oct 27, 2015 2:40 pm

I solved it.

I made a recursive call template to pick up the continuation lines. Works well.

I also wrote some functions to test the text--only to make the code more readable.

I don't know if using a recursive call template fits the xslt idiom well, but it's done.

I really thought a <for-each..> or <for-each-group..> was more appropriate, but I couldn't get them to work.

Code: Select all

<xsl:template match="notes/p[mf:newline(.)]">
        <p>
            <xsl:copy-of select="text()"/>
            <xsl:call-template name="cont">
                <xsl:with-param name="loop-count" select="1"/>
            </xsl:call-template>
        </p>
    </xsl:template>
   
    <xsl:template name="cont">
        <xsl:param name="loop-count"/>
        <xsl:if test="following::p[$loop-count][mf:contline(.)]">
           
            <xsl:variable name="next-text" select="following::p[$loop-count]/text()"/>
            <xsl:value-of select="concat(' ',normalize-space($next-text))"/>
            <xsl:call-template name="cont">
                <xsl:with-param name="loop-count" select="$loop-count+1"/>
            </xsl:call-template>
           
        </xsl:if>       
    </xsl:template>
   

Return to “XSLT and FOP”

Who is online

Users browsing this forum: No registered users and 0 guests