Background
I was recently surprised to notice that XSL was able to intelligently handle numbers; i.e. knowing to treat numbers in text as numeric when performing comparisons (i.e. it understood that 7 < 10 rather than thinking '10' < '7'). In my case that's what I wanted; just not what I'd expected.
Out of curiosity I then tried to force XSLT to compare the numbers as strings (i.e. by using the string() function, but with no luck.
Question
Is it possible to get XSLT to compare numbers as strings; e.g. so '10' < '7'?
Example
Source XML:
<?xml version="1.0" encoding="utf-8"?>
<element>
<x>1</x>
<x>2</x>
<x>3</x>
<x>4</x>
<x>5</x>
<x>6</x>
<x>7</x>
<x>8</x>
<x>9</x>
<x>10</x>
</element>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="element">
<element>
<AsItComes>
<xsl:for-each select="./x">
<xsl:if test="./text() < 7">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:if>
</xsl:for-each>
</AsItComes>
<AsNumber>
<xsl:for-each select="./x">
<xsl:if test="number(./text()) < 7">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:if>
</xsl:for-each>
</AsNumber>
<AsString>
<xsl:for-each select="./x">
<xsl:if test="string(./text()) < '7'">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:if>
</xsl:for-each>
</AsString>
</element>
</xsl:template>
</xsl:stylesheet>
Expected Output:
<?xml version="1.0" encoding="utf-8"?>
<element>
<AsItComes>
<x>1</x>
<x>2</x>
<x>3</x>
<x>4</x>
<x>5</x>
<x>6</x>
<x>10</x>
</AsItComes>
<AsNumber>
<x>1</x>
<x>2</x>
<x>3</x>
<x>4</x>
<x>5</x>
<x>6</x>
</AsNumber>
<AsString>
<x>1</x>
<x>2</x>
<x>3</x>
<x>4</x>
<x>5</x>
<x>6</x>
<x>10</x>
</AsString>
</element>
Actual Output:
<?xml version="1.0" encoding="utf-8"?>
<element>
<AsItComes>
<x>1</x>
<x>2</x>
<x>3</x>
<x>4</x>
<x>5</x>
<x>6</x>
</AsItComes>
<AsNumber>
<x>1</x>
<x>2</x>
<x>3</x>
<x>4</x>
<x>5</x>
<x>6</x>
</AsNumber>
<AsString>
<x>1</x>
<x>2</x>
<x>3</x>
<x>4</x>
<x>5</x>
<x>6</x>
</AsString>
</element>
It appears that in XSLT/XPATH 1.0, the
string()value is still evaluated as a number when performing the comparison.https://www.w3.org/TR/xpath/#booleans
With XSLT/XPATH 2.0 (and 3.0, and 3.1), you can explicitly set the data type as
xs:stringto ensure that the comparison is performed against strings and not coerced into number values.But it is sufficient to compare the value to the string
'7'(also, you could eliminate the<xsl:if>and put your filter in a predicate):