XSLT multiple replacement

I have an XML document, something like

<root> <item>_x0034_SOME TEXT</item> <item>SOME_x0020_TEXT</item> <item>SOME_x0020_TEXT_x0032_</item> </root> 

I export it to HTML, but I'm having trouble replacing escape characters. I found several patterns on the Internet for replacing text, but they all look like this:

 <xsl:template name="replaceString"> <xsl:param name="strOrig"/> <xsl:param name="strSearch"/> <xsl:param name="strReplace"/> <xsl:choose> <xsl:when test="contains($strOrig, $strSearch)"> <xsl:value-of select="substring-before($strOrig, $strSearch)"/> <xsl:value-of select="$strReplace"/> <xsl:call-template name="replaceString"> <xsl:with-param name="strOrig" select="substring-after($strOrig, $strSearch)"/> <xsl:with-param name="strSearch" select="$strSearch"/> <xsl:with-param name="strReplace" select="$strReplace"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$strOrig"/> </xsl:otherwise> </xsl:choose> </xsl:template> 

I'm not sure how I can use this to make multiple replacements. I tried this:

 <xsl:for-each select="PinnacleSys.PMC.Plugins.PVR.PvrChannelDescriptorWrapper/PinnacleSys.PMC.Plugins.PVR.DVBTPvrChannelDescriptor"> <!--name="<xsl:value-of select="replace(replace(Name, '_x0020_', ' '), '_x0034_', '3')"/>" --> <!--name="<xsl:value-of select="Name"/>"--> <xsl:variable name="var1" select="Text" /> <xsl:value-of select="replace($FeatureInfo,'Feature=','TESTING')"/> name=" <xsl:call-template name="replaceString"> <xsl:with-param name="strOrig" select="Name"/> <xsl:with-param name="strSearch" select="'_x0020_'"/> <xsl:with-param name="strReplace" select="' '"/> </xsl:call-template> <xsl:call-template name="replaceString"> <xsl:with-param name="strOrig" select="Name"/> <xsl:with-param name="strSearch" select="'_x0030_'"/> <xsl:with-param name="strReplace" select="'0'"/> </xsl:call-template> ..." 

But this is just a string concatenation several times, each with a different replacement. I also studied variables; if I could assign the result of calling the template to a variable, I could get a dirty but working solution, which is enough for me. However, I could not and do not know if this is possible.

What is the best way to do this?

I am limited to 1.0 XSLT (with 2.0 I could call one replace () inside another).

+4
source share
4 answers

For an XSLT 1.0 proprietary solution using a replacement template, the individual replacements must be nested, as shown here. This is obviously inefficient due to the potential number of replacements. The optimized version is given below.

 <xsl:template match="item"> <xsl:copy> <xsl:call-template name="replace-substring"> <xsl:with-param name="original"> <xsl:call-template name="replace-substring"> <xsl:with-param name="original"> <xsl:call-template name="replace-substring"> <xsl:with-param name="original" select="."/> <xsl:with-param name="substring" select="'_x0020_'"/> <xsl:with-param name="replacement" select="' '"/> </xsl:call-template> </xsl:with-param> <xsl:with-param name="substring" select="'_x0032_'"/> <xsl:with-param name="replacement" select="'2'"/> </xsl:call-template> </xsl:with-param> <xsl:with-param name="substring" select="'_x0034_'"/> <xsl:with-param name="replacement" select="'4'"/> </xsl:call-template> </xsl:copy> </xsl:template> <xsl:template name="replace-substring"> <xsl:param name="original"/> <xsl:param name="substring"/> <xsl:param name="replacement" select="''"/> <xsl:choose> <xsl:when test="contains($original, $substring)"> <xsl:value-of select="substring-before($original, $substring)"/> <xsl:copy-of select="$replacement"/> <xsl:call-template name="replace-substring"> <xsl:with-param name="original" select="substring-after($original, $substring)"/> <xsl:with-param name="substring" select="$substring"/> <xsl:with-param name="replacement" select="$replacement"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$original"/> </xsl:otherwise> </xsl:choose> </xsl:template> 

Since the output is HTML (XML will also be fine), strings _xNNNN_ can be converted to their hexadecimal numeric character references, for example, &#xNNNN; . This template is effective.

 <xsl:template match="item"> <xsl:copy> <xsl:call-template name="replaceChars"> <xsl:with-param name="original" select="."/> </xsl:call-template> </xsl:copy> </xsl:template> <xsl:template name="replaceChars"> <xsl:param name="original"/> <xsl:choose> <xsl:when test="contains($original, '_x')"> <xsl:value-of select="substring-before($original, '_x')"/> <xsl:variable name="after" select="substring-after($original, '_x')"/> <xsl:variable name="char" select="substring-before($after, '_')"/> <xsl:value-of select="concat('&amp;#x',$char,';')" disable-output-escaping="yes"/> <xsl:call-template name="replaceChars"> <xsl:with-param name="original" select="substring-after($after, '_')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$original"/> </xsl:otherwise> </xsl:choose> </xsl:template> 

This is the resulting conclusion.

 <root> <item>&#x0034;SOME TEXT</item> <item>SOME&#x0020;TEXT</item> <item>SOME&#x0020;TEXT&#x0032;</item> </root> 
+5
source

XSLT 1.0 is no better for replacing strings. The template you have will be the one to be used. However, to replace strings, I use string substitution in another language, usually JavaScript or C # / VB.NET (Java or any other language will work too). Presumably, at some point, the XML document is serialized into a string. Once this is a string, use simple string or string replacements for more complex comparisons.

+1
source

Place the template call inside the variable body.

 <xsl:variable name="myVar"><xsl:call-template name="replaceString"> <xsl:with-param name="strOrig" select="Name"/> <xsl:with-param name="strSearch" select="'_x0020_'"/> <xsl:with-param name="strReplace" select="' '"/> </xsl:call-template> </xsl:variable> 

Assign your content to myVar.

+1
source

Take a look at the support for regular expressions in EXSLT (www.exslt.org). EXSLT support is available on most modern XSL processors.

+1
source

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


All Articles