Joh*_*van 7 xslt comparison string-comparison numeric-conversion
背景
我最近惊讶地注意到XSL能够智能地处理数字; 即在进行比较时知道将文本中的数字视为数字(即它理解7 < 10
而不是思考'10' < '7'
).就我而言,这就是我想要的; 只是不是我所期待的.
出于好奇,我试图强迫XSLT将数字作为字符串进行比较(即通过使用string()
函数,但没有运气.
题
是否有可能让XSLT将数字作为字符串进行比较; 比如这样'10' < '7'
?
例
源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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
预期产出:
<?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>
Run Code Online (Sandbox Code Playgroud)
实际产量:
<?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>
Run Code Online (Sandbox Code Playgroud)
看来在XSLT/XPATH 1.0中,string()
在执行比较时仍将值评估为数字.
https://www.w3.org/TR/xpath/#booleans
当要比较的对象都不是节点集并且运算符是<=,<,> =或>时,则通过将两个对象转换为数字并根据IEEE 754比较数字来比较对象.<比较将是当且仅当第一个数字小于第二个数字时才返回true.
使用XSLT/XPATH 2.0(以及3.0和3.1),您可以显式设置数据类型,xs:string
以确保对字符串执行比较而不是强制转换为数字值.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.0">
<xsl:template match="element">
<element>
<AsString>
<xsl:for-each select="./x">
<xsl:if test="xs:string(.) < xs:string('7')">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:if>
</xsl:for-each>
</AsString>
</element>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
但是将值与字符串进行比较就足够了'7'
(同样,你可以消除<xsl:if>
并将过滤器放在谓词中):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="element">
<element>
<AsString>
<xsl:for-each select="./x[. < '7']">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:for-each>
</AsString>
</element>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)