我需要比较表示整数的XML属性,但可以使用XPath / XSLT-1.0以十进制或十六进制(带有0x前缀)给出。
这是一个(不工作的)XSLT来演示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="iso-8859-1" omit-xml-declaration="yes" />
<xsl:template match="//node">
<xsl:if test="@value > 2">
<xsl:value-of select="@value"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
这是输入的XML:
<?xml version="1.0" encoding="UTF-8"?>
<body>
<node value="1"/>
<node value="3"/>
<node value="0x03"/>
</body>
这是所需的输出。格式并不重要;重要的只是第二个和第三个节点上存在匹配:
3 0x03
第二个节点上只有一个匹配项;十六进制节点不会被XML解释为数字。任何人都可以想到这个问题的合理解决方案吗?
答案 0 :(得分:4)
格式并不重要;
然后为方便起见,我将使用XML格式演示输出:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/body">
<xsl:copy>
<xsl:for-each select="node">
<xsl:variable name="decimal">
<xsl:choose>
<xsl:when test="starts-with(@value, '0x')">
<xsl:call-template name="hex2num">
<xsl:with-param name="hex" select="substring-after(@value, '0x')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="$decimal > 2">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template name="hex2num">
<xsl:param name="hex"/>
<xsl:param name="num" select="0"/>
<xsl:param name="MSB" select="translate(substring($hex, 1, 1), 'abcdef', 'ABCDEF')"/>
<xsl:param name="value" select="string-length(substring-before('0123456789ABCDEF', $MSB))"/>
<xsl:param name="result" select="16 * $num + $value"/>
<xsl:choose>
<xsl:when test="string-length($hex) > 1">
<xsl:call-template name="hex2num">
<xsl:with-param name="hex" select="substring($hex, 2)"/>
<xsl:with-param name="num" select="$result"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$result"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
应用于以下测试输入:
<body>
<node value="1"/>
<node value="0x02"/>
<node value="3"/>
<node value="0x04"/>
<node value="0xB1"/>
</body>
产生结果:
<?xml version="1.0" encoding="UTF-8"?>
<body>
<node value="3"/>
<node value="0x04"/>
<node value="0xB1"/>
</body>
答案 1 :(得分:1)
由于您说您的处理器是MSXSL,因此您可以使用msxsl
扩展,这样您就可以使用define a script来处理XSLT处理器本身无法完成的工作。
以下使用一个小型JScript函数,将所有以0x
开头的十六进制数转换为十进制数。
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:script="http://tempuri.org/script"
exclude-result-prefixes="msxsl script"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/body">
<xsl:copy>
<xsl:copy-of select="node[script:hexToDec(@value) > 2]" />
</xsl:copy>
</xsl:template>
<msxsl:script language="jscript" implements-prefix="script"><![CDATA[
function hexToDec(nodeList) {
var firstNode, matches;
if (nodeList.length) {
firstNode = nodeList.nextNode();
matches = /^\s*0x0*([0-9A-F]+)\s*$/i.exec(firstNode.text);
return matches ? parseInt(matches[1], 16) : firstNode.text;
}
return "";
}
]]></msxsl:script>
</xsl:stylesheet>
msxsl
命名空间还允许更高级的扩展XSLT处理器的方法,例如使用COM DLL或.NET代码,但对于这个简单的场景,JScript就可以了。