与 XSLT 进行区域感知数字比较
Posted
技术标签:
【中文标题】与 XSLT 进行区域感知数字比较【英文标题】:locale-aware number comparison with XSLT 【发布时间】:2010-09-30 09:55:47 【问题描述】:我的 XML 中有一堆成本,我试图将它们与另一个成本值进行比较,以确定要显示的值(仅高于比较器的值)。这适用于数字使用小数点作为分隔符但不适用于使用逗号作为小数分隔符的数字。我可能会得到任何一个,这取决于语言环境。
这是我所拥有的:
<patron_max_cost><![CDATA[1,00]]></patron_max_cost>
<service_costs>
<location_cost>
<location_desc><![CDATA[location1]]></location_desc>
<cost_to_user><![CDATA[0,99]]></cost_to_user>
</location_cost>
<location_cost>
<location_desc><![CDATA[location2]]></location_desc>
<cost_to_user><![CDATA[1,50]]></cost_to_user>
</location_cost>
</service_costs>
<xsl:variable name="filtered_location_costs">
<xsl:for-each select="service_costs/location_cost">
<xsl:if test="number(cost_to_user) > number(patron_max_cost)">
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:variable>
这失败了,因为 cost_to_user 和patron_max_cost 是 NaN。有没有一种方法可以进行这种比较,既适用于两种输入样式,又不涉及在比较之前将逗号转换为小数点等笨拙的东西?我正在使用 XSLT2.0 和 Saxon8。
【问题讨论】:
为什么选择 CDATA 部分?使用fn:traslate
并不笨拙。如果您想要自己的数字格式,则必须定义自己的 大于 运算符。
好问题 (+1)。请参阅我的答案以获得简短而完整的解决方案。 :)
【参考方案1】:
我。 XSLT 1.0 解决方案:
这种转变:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"location_cost[not(translate(cost_to_user, ',', '.')
>
translate(/*/patron_max_cost, ',', '.')
)
]
"/>
</xsl:stylesheet>
应用于提供的 XML 文档时:
<t>
<patron_max_cost><![CDATA[1,00]]></patron_max_cost>
<service_costs>
<location_cost>
<location_desc><![CDATA[location1]]></location_desc>
<cost_to_user><![CDATA[0,99]]></cost_to_user>
</location_cost>
<location_cost>
<location_desc><![CDATA[location2]]></location_desc>
<cost_to_user><![CDATA[1,50]]></cost_to_user>
</location_cost>
</service_costs>
</t>
产生想要的结果:
<t>
<patron_max_cost>1,00</patron_max_cost>
<service_costs>
<location_cost>
<location_desc>location2</location_desc>
<cost_to_user>1,50</cost_to_user>
</location_cost>
</service_costs>
</t>
二。 XSLT 2.0 解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vpatron_max_cost" as="xs:decimal"
select="xs:decimal(translate(/*/patron_max_cost, ',', '.'))"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"location_cost[xs:decimal(translate(cost_to_user, ',', '.'))
le
$vpatron_max_cost
]
"/>
</xsl:stylesheet>
【讨论】:
感谢 Dimitre,这比我想象的要简单。我也很欣赏扩展的答案。【参考方案2】:我会使用从逗号到十进制的转换,但也会首先保留一个变量是否有逗号,以便我可以正确显示它(即,将其转换回来。
【讨论】:
以上是关于与 XSLT 进行区域感知数字比较的主要内容,如果未能解决你的问题,请参考以下文章
在 Android 中是不是可以对 Numberformat 进行区域感知解析?
全景驾驶感知网络YOLOP部署与实现(交通目标检测可驾驶区域分割车道线检测)
自动驾驶感知系统实现(车道线检测和拟合目标检测与跟踪道路可行驶区域分割深度估计图像视野到BEV空间映射像平面到地平面映射)