How to extract unique characters from a string using XSLT 1.0?

One of the most difficult issues I've ever encountered while designing XSLT.

How to copy unique characters in a given string.
Test xml:

<root> <string>aaeerstrst11232434</string> </root> 

Expected Result:

 <string>aerst1234</string> 
+4
source share
4 answers

Here is the XSLT 1.0 solution, smaller than the selected answer, and it is easier to write because it uses the str-foldl FXSL template .

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://fxsl.sf.net/" exclude-result-prefixes="f"> <xsl:import href="str-foldl.xsl"/> <xsl:output method="text"/> <f:addUnique/> <xsl:variable name="vFunAddunique" select= "document('')/*/f:addUnique[1] "/> <xsl:template match="string"> <xsl:call-template name="str-foldl"> <xsl:with-param name="pFunc" select="$vFunAddunique"/> <xsl:with-param name="pA0" select="''"/> <xsl:with-param name="pStr" select="."/> </xsl:call-template> </xsl:template> <xsl:template match="f:addUnique" mode="f:FXSL"> <xsl:param name="arg1"/> <xsl:param name="arg2"/> <xsl:value-of select="$arg1"/> <xsl:if test="not(contains($arg1, $arg2))"> <xsl:value-of select="$arg2"/> </xsl:if> </xsl:template> </xsl:stylesheet> 

When the above conversion is applied to the originally provided XML source document :

 <root> <string>aaeerstrst11232434</string> </root> 

the desired result is obtained :

 aerst1234 

Read more about FXSL 1.x (for XSLT 1.0) here , as well as FXSL 2.x (for XSLT 2.0) here .

+1
source

Use the following XPath single-line interface :

 codepoints-to-string(distinct-values(string-to-codepoints(.))) 

Complete conversion using this below :

 <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output method="text"/> <xsl:template match="string"> <xsl:value-of select= "codepoints-to-string(distinct-values(string-to-codepoints(.))) "/> </xsl:template> </xsl:stylesheet> 

When this conversion is applied to the originally provided XML document :

 <root> <string>aaeerstrst11232434</string> </root> 

the desired result is obtained :

 aerst1234 

If you need a solution XSLT 1.0 - please indicate this, and I will provide it.

+3
source

Here is the XSLT 1.0 solution:

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:strip-space elements="*"/> <xsl:output method="text"/> <xsl:template match="string"> <xsl:call-template name="unique"> <xsl:with-param name="input" select="."/> </xsl:call-template> </xsl:template> <xsl:template name="unique"> <xsl:param name="input"/> <xsl:param name="output" select="''"/> <xsl:variable name="c" select="substring($input, 1, 1)"/> <xsl:choose> <xsl:when test="not($input)"> <xsl:value-of select="$output"/> </xsl:when> <xsl:when test="contains($output, $c)"> <xsl:call-template name="unique"> <xsl:with-param name="input" select="substring($input, 2)"/> <xsl:with-param name="output" select="$output"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="unique"> <xsl:with-param name="input" select="substring($input, 2)"/> <xsl:with-param name="output" select="concat($output, $c)"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> 
+3
source

When I tried with more complex XML, I ran into a lot of problems with Martin Honnen , it doesn’t work with the XML below, so I prepared my own solution referencing Dimitre with this answer. And also I could call it a more efficient solution:

Here is the xml input:

  <root> <string>aabcdbcd1abcdefghijklmanopqrstuvwxyzabcdefgh0123456789ijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12312489796453134049446798421230156489413210315487804210313264046040489789789745648974321231564648971232344</string> <string2>oejrinsjfojofjweofj24798273492jfakjflsdjljk</string2> </root> 

And here is the working XSLT code:

  <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="text()"> <xsl:call-template name="unique_chars"> <xsl:with-param name="input" select="."/> </xsl:call-template> </xsl:template> <xsl:template name="unique_chars"> <xsl:param name="input"/> <xsl:variable name="c"> <xsl:value-of select="substring($input, 1, 1)"/> </xsl:variable> <xsl:choose> <xsl:when test="not($input)"/> <xsl:otherwise> <xsl:choose> <xsl:when test="contains(substring($input, 2), $c)"> <xsl:call-template name="unique_chars"> <xsl:with-param name="input" select="substring($input, 2)"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$c"/> <xsl:call-template name="unique_chars"> <xsl:with-param name="input" select="substring($input, 2)"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> 
0
source

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


All Articles