在回答本网站上的另一个XSLT问题时,我偶然发现了XSLT1.0和2.0之间的一个我不理解的区别。谁能解释这里发生了什么,以及如何解决差异
注意:我使用的是XML Spy版本2011 sp1(x64)。
我的输入XML是
<?xml version="1.0" encoding="UTF-8"?>
<root>
<Manager grade="10" id="26">
<Employee id="1" grade="9"/>
<Employee id="2" grade="8"/>
</Manager>
<Manager grade="10" id="27">
<Employee id="3" grade="9"/>
<Employee id="4" grade="8"/>
<Employee id="5" grade="4"/>
</Manager>
<Manager grade="7" id="28">
<Employee id="6" grade="8"/>
<Employee id="7" grade="7"/>
<Employee id="8" grade="6"/>
<Employee id="9" grade="9"/>
</Manager>
<Manager grade="9" id="29">
<Employee id="10" grade="9"/>
<Employee id="11" grade="8"/>
<Employee id="12" grade="7"/>
</Manager>
</root>
我希望选择一组级别大于或等于经理级别的员工。为此,我编写了以下1.0转换:
<?xml version="1.0" encoding="UTF-8"?>
<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:template match="/">
<root>
<xsl:apply-templates select="root/Manager"/>
</root>
</xsl:template>
<xsl:template match="Manager">
<mgr>
<managerId><xsl:value-of select="@id"/></managerId>
<managerGrade><xsl:value-of select="@grade"/></managerGrade>
<empsSelection>
<xsl:copy-of select="Employee[@grade >= ../@grade]"/>
</empsSelection>
</mgr>
</xsl:template>
</xsl:stylesheet>
输出是预期的
<?xml version="1.0" encoding="UTF-8"?>
<root>
<mgr>
<managerId>26</managerId>
<managerGrade>10</managerGrade>
<empsSelection/>
</mgr>
<mgr>
<managerId>27</managerId>
<managerGrade>10</managerGrade>
<empsSelection/>
</mgr>
<mgr>
<managerId>28</managerId>
<managerGrade>7</managerGrade>
<empsSelection>
<Employee id="6" grade="8"/>
<Employee id="7" grade="7"/>
<Employee id="9" grade="9"/>
</empsSelection>
</mgr>
<mgr>
<managerId>29</managerId>
<managerGrade>9</managerGrade>
<empsSelection>
<Employee id="10" grade="9"/>
</empsSelection>
</mgr>
</root>
但是,当我将XSLT版本更改为2.0(采用上面的样式表并将stylesheet/@version更改为2.0)时,我会得到以下不同且出乎意料的结果:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<mgr>
<managerId>26</managerId>
<managerGrade>10</managerGrade>
<empsSelection>
<Employee id="1" grade="9"/>
<Employee id="2" grade="8"/>
</empsSelection>
</mgr>
<mgr>
<managerId>27</managerId>
<managerGrade>10</managerGrade>
<empsSelection>
<Employee id="3" grade="9"/>
<Employee id="4" grade="8"/>
<Employee id="5" grade="4"/>
</empsSelection>
</mgr>
<mgr>
<managerId>28</managerId>
<managerGrade>7</managerGrade>
<empsSelection>
<Employee id="6" grade="8"/>
<Employee id="7" grade="7"/>
<Employee id="9" grade="9"/>
</empsSelection>
</mgr>
<mgr>
<managerId>29</managerId>
<managerGrade>9</managerGrade>
<empsSelection>
<Employee id="10" grade="9"/>
</empsSelection>
</mgr>
</root>
为什么要更改样式表,以及应该如何更改样式表才能在XSLT1.0和2.0版本中获得正确的结果?
我认为在XSLT2.0中,默认情况下可以将比较作为字符串,而在XSLT1.0中,比较运算符首先将任何操作数转换为数字,然后进行比较,因此在XSLT2.0中,您需要
<xsl:template match="Manager">
<mgr>
<managerId><xsl:value-of select="@id"/></managerId>
<managerGrade><xsl:value-of select="@grade"/></managerGrade>
<empsSelection>
<xsl:copy-of select="Employee[number(@grade) >= number(current()/@grade)]"/>
</empsSelection>
</mgr>
</xsl:template>
以获得您想要的结果。当然,使用像xs:integer(@grade)
这样的其他数字类型也应该如此。