How do I apply a change to text in an element without losing its child elements.
For example:
I have this xml that I would like to apply a change to the text inside the ‘p’ element….
<section> <p >Awesome LO</p> <p > Begin with an interesting fact, thought-provoking <keyword>question</keyword> <context> <p type='Key Words Head'>Banana</p> <p type='Key Words'>A tasty treat to eat any time, and good with ice cream – a banana split.</p> </context>, or a one sentence scenario to illustrate why the learning object (content) is important. </p> <p > Begin with a definition, if required. Then, provide an example by example view. </p> </section>
So my xsl looks like this….
<xsl:template match='p'> <xsl:copy> <xsl:call-template name='widont-title'> <xsl:with-param name='text' select='text()' /> </xsl:call-template> </xsl:copy> </xsl:template>
The problem is that I lose the ‘keyword’, ‘context’, and other elements inside of the ‘p’ when I do this. Can anyone point me to any clues? Thanks!
<!-- this method puts a non breaking space in the last word of a 'p' if its less than 5 characters--> <xsl:template name='widont-title'> <xsl:param name='temp'/> <xsl:param name='text'/> <xsl:param name='minWidowLength' select='5'/> <xsl:choose> <xsl:when test='contains($text, ' ')'> <xsl:variable name='prev' select='substring-before($text,' ')'/> <xsl:variable name='before' select='concat($temp,' ',$prev)'/> <xsl:variable name='after' select='substring-after($text, ' ')'/> <xsl:choose> <xsl:when test='contains($after, ' ')'> <xsl:call-template name='widont-title'> <xsl:with-param name='temp' select='$before'/> <xsl:with-param name='text' select='$after'/> </xsl:call-template> </xsl:when> <xsl:when test='not(contains($after, ' ')) and string-length(translate($after,'`~!@#$%^\*()-_=+\\|]}[{;:,./?<>','')) < $minWidowLength'> <xsl:value-of select='concat($before, ' ', $after)' /> </xsl:when> <xsl:otherwise> <xsl:value-of select='concat($before, ' ', $after)' /> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:value-of select='$text'/> </xsl:otherwise> </xsl:choose> </xsl:template>
It is not clear what the
widont-titletemplate does and whether this is correctly implemented (looks a little-bit too-complicated), but the problem is that this template is applied too-soon, not leaving any possibilities for children elements ofpto be processed.The solution (using the identity template and overriding it for
p/text()nodes) is very simple:when the above transformation is applied on the provided XML document, the children of any
pelement are correctly present in the output.