How to change text in an element using xsl

How to apply a change to the text in an element without losing its children.

For example:

I have this xml that I would like to apply 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 the “p” when I do this. Can someone give me some hints? 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,'`~!@#$%^\*()-_=+\\|]}[{;:,./?&lt;&gt;','')) &lt; $minWidowLength">

                    <xsl:value-of select="concat($before, '&#160;', $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>
+3
source share
1 answer

It is not clear what the template does and whether it is implemented correctly (it looks a bit too complicated), but the problem is that this template is applied too soon, leaving no room for processing child elements . widont-titlep

( p/text()) :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="p/text()">
        <xsl:call-template name="widont-title">
            <xsl:with-param name="text" select="." />
        </xsl:call-template>
    </xsl:template>

         <!-- "widont-title" template omitted for brevity -->

</xsl:stylesheet>

, XML-, p .

+5

Source: https://habr.com/ru/post/1706350/


All Articles