Разница в обработке правил шаблона XSLT 1.0 и 2.0 - PullRequest
0 голосов
/ 16 февраля 2012

Отвечая на другой вопрос по 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 Ответ

1 голос
/ 16 февраля 2012

Я думаю, что в 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).

...