Search code examples
xsltstringline-breaksapply-templatespreserve

string processing with xsl:apply-templates


I have a xml that looks like this,

<Parent> Running text with marked up entities like 
  <Child>Entity1</Child> 
 and, text in the middle too, and
  <Child> Entity2 </Child>
</Parent>

I have to preserve the line breaks and indentation when rendering the parent, but also apply a highlighting template to every child tag.

Now, the moment I capture the contents of the parent tag in a variable to do some string processing in XSL, I lose the underlying xml structure and cant apply the highlighting template to the children.

Whereas, I cant think of any other way to preserve the line breaks and indentation of the text contained in the parent tag.

Any ideas?


Solution

  • This stylesheet:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:preserve-space elements="*"/>
        <xsl:template match="Parent">
            <div>
                <xsl:apply-templates mode="preserve"/>
            </div>
        </xsl:template>
        <xsl:template match="text()" mode="preserve" name="split">
            <xsl:param name="pString" select="."/>
            <xsl:choose>
                <xsl:when test="contains($pString,'&#xA;')">
                    <xsl:value-of select="substring-before($pString,'&#xA;')"/>
                    <br/>
                    <xsl:call-template name="split">
                        <xsl:with-param name="pString"
                         select="substring-after($pString,'&#xA;')"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$pString"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
        <xsl:template match="Child" mode="preserve">
            <b>
                <xsl:apply-templates mode="preserve"/>
            </b>
        </xsl:template>
    </xsl:stylesheet>
    

    Output:

    <div> Running text with marked up entities like<br/> <b>Entity1</b><br/> and, text in the middle too, and<br/> <b> Entity2 </b><br/></div>

    Render as:

    Running text with marked up entities like
    Entity1
    and, text in the middle too, and
    Entity2


    Edit: Better example preserving whitespace only text nodes.