Reputation: 19385
Given the following fragment:
<recipe>
get a bowl
<ingredient>flour</ingredient>
<ingredient>milk</ingredient>
mix it all together!
</recipe>
How can I match "get a bowl
" and "mix it all together!
" and wrap them in another element to create the following?
<recipe>
<action>get a bowl</action>
<ingredient>flour</ingredient>
<ingredient>milk</ingredient>
<action>mix it all together!</action>
</recipe>
Upvotes: 2
Views: 141
Reputation: 122374
You could define a template matching text nodes that are a direct child of recipe
:
<xsl:template match="recipe/text()">
<action><xsl:value-of select="normalize-space()" /></action>
</xsl:template>
Full XSLT example:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*" />
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
</xsl:template>
<xsl:template match="recipe/text()">
<action><xsl:value-of select="normalize-space()" /></action>
</xsl:template>
</xsl:stylesheet>
Note that the normalize-space()
is required, even with the xsl:strip-space
- that only affects text nodes that contain only whitespace, it doesn't strip off leading and trailing space from nodes that contain any non-whitespace characters. If you had
<action><xsl:value-of select="." /></action>
then the result would be something like
<recipe>
<action>
get a bowl
</action>
<ingredient>flour</ingredient>
<ingredient>milk</ingredient>
<action>
mix it all together!
</action>
</recipe>
Upvotes: 4