模板规则处理XSLT 1.0与2.0的区别

时间:2012-02-16 12:13:25

标签: xslt-2.0 xslt-1.0 string-comparison

在这个网站上回答另一个XSLT问题,我偶然发现了我不理解的XSLT 1.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 &gt;= ../@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(使用上面的样式表并将样式表/ @版本更改为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>

为什么要更改样式表以便在XSLT 1.0和2.0版本中获得正确的结果?

1 个答案:

答案 0 :(得分:1)

我认为使用XSLT 2.0,默认情况下会将比较作为字符串进行比较,而使用XSLT 1.0,比较运算符首先将所有操作数转换为数字,然后将其与您需要的XSLT 2.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) &gt;= number(current()/@grade)]"/>
        </empsSelection>
    </mgr>
</xsl:template>

获得您想要的结果。当然,使用xs:integer(@grade)等其他数字类型也应该这样做。