Page 1 of 1

XSLT: Problem merging following elements

Posted: Mon Oct 26, 2015 5:58 pm
by boater
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?

Re: XSLT: Problem merging following elements

Posted: Tue Oct 27, 2015 2:40 pm
by boater
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>