xpath 2.0 выбор элементов по атрибуту

Я использовал следующий выбор xpath в xpath 1.0

<xsl:variable name="id"><xsl:value-of select="./@id" /></xsl:variable>
preceding::exm:messageFlow[@sourceRef = $id]/@targetRef

Это сработало очень хорошо и сделало именно то, что я хотел. Однако я начал использовать XSLT 2.0 в сочетании с xPath 2.0, и это больше не работает (используя XML-процессор Altova). Я получаю следующую ошибку:

Kann nicht mit Ziel-Typ besetzt werden - Aktuelles Element ist 'sid-B3FD7EE5-043 3-4939-A69F-E74B30FDEB1C' vom Typ xs:untypedAtomic, Typ xs:QName erwartet - =

что примерно переводится как:

Невозможно установить целевой тип — Текущий элемент — «sid-B3FD7EE5-043 3-4939-A69F-E74B30FDEB1C» типа xs:untypedAtomic, ожидается тип xs:QName —

Раньше у меня была аналогичная проблема с этим выбором:

following::exm:*[exm:incoming = $out] | preceding::exm:*[exm:incoming = $out]

Который снова работал в xpath 1.0, но возвращал аналогичную ошибку в xPath 2.0. После изменения его на

following::exm:*[exm:incoming/text() = $out] | preceding::exm:*[exm:incoming/text() = $out]

Это работало и в xPath 2.0. Я пытался сделать что-то подобное с атрибутами, но это не сработало.

Небольшой отрывок из соответствующего XML:

<messageFlow id="sid-80B618A4-E6BF-4438-AF5D-5111AD308FE6" name="" sourceRef="sid-B3FD7EE5-0433-4939-A69F-E74B30FDEB1C" targetRef="sid-6EB2DB76-CC19-48AD-A073-D37C7489F211"/>
<task completionQuantity="1" id="sid-B3FD7EE5-0433-4939-A69F-E74B30FDEB1C" isForCompensation="false" name="call service" startQuantity="1">
     <incoming>sid-2B2BA651-B5BA-4195-9B5B-E6855B1138F4</incoming>
     <incoming>sid-DA4B86E8-C3F2-497C-8C0D-218E95CE9FD1</incoming>
     <outgoing>sid-008948DE-BA59-4897-AC37-2C3AA63DCD82</outgoing>
</task>

person Simon    schedule 26.07.2012    source источник


Ответы (2)


Интересно, есть ли у вас схема, которая объявляет атрибут @id как имеющий тип QName?

С этим объявлением переменной:

<xsl:variable name="id"><xsl:value-of select="./@id" /></xsl:variable>

вы создаете копию атрибута @id в новом фрагменте дерева результатов. Это совершенно не нужно; ваши потребности почти наверняка будут лучше удовлетворены, если переменная будет просто ссылкой на существующий атрибут, таким образом:

<xsl:variable name="id" select="@id" />

Делая копию, вы не только пишете ненужный код и несете ненужные затраты во время выполнения (построение нового дерева — дорогостоящая операция), но вы также теряете информацию о типе. Если моя догадка верна, что @id имеет тип xs:QName, то переменная $id после атомизации будет иметь тип xs:untypedAtomic, и сравнение ее с xs:QName, скорее всего, не удастся с сообщением, подобным приведенному .

person Michael Kay    schedule 26.07.2012
comment
Вы были совершенно правы насчет проблемы со схемой. После того, как я удалил всю информацию о схеме из исходного xml-файла, Alova больше не выдавала ошибок, и все заработало как положено. Я попытался сохранить схему и изменить переменную, как вы описали. Однако ошибка все еще сохранялась. Спасибо, что указали, как я могу улучшить код. - person Simon; 27.07.2012

Я не могу воспроизвести проблему.

Это преобразование:

<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:template match="task">
    <xsl:variable name="id"><xsl:value-of select="./@id" /></xsl:variable>

    <xsl:variable name="vResult"
     select="preceding::messageFlow[@sourceRef = $id]/@targetRef"/>

    <xsl:value-of select="$vResult"/>
 </xsl:template>
</xsl:stylesheet>

при применении к следующему документу (предоставленный фрагмент заключен в один верхний элемент и лишен всех неопределенных пространств имен):

<t>
    <messageFlow id="sid-80B618A4-E6BF-4438-AF5D-5111AD308FE6"
    name="" sourceRef="sid-B3FD7EE5-0433-4939-A69F-E74B30FDEB1C"
    targetRef="sid-6EB2DB76-CC19-48AD-A073-D37C7489F211"/>
    <task completionQuantity="1" id="sid-B3FD7EE5-0433-4939-A69F-E74B30FDEB1C"
    isForCompensation="false" name="call service" startQuantity="1">
         <incoming>sid-2B2BA651-B5BA-4195-9B5B-E6855B1138F4</incoming>
         <incoming>sid-DA4B86E8-C3F2-497C-8C0D-218E95CE9FD1</incoming>
         <outgoing>sid-008948DE-BA59-4897-AC37-2C3AA63DCD82</outgoing>
    </task>
</t>

при запуске как с Altova2011, так и с Saxon 9.1.07 выдает ожидаемый правильный результат и не возникает никаких ошибок:

sid-6EB2DB76-CC19-48AD-A073-D37C7489F211
person Dimitre Novatchev    schedule 26.07.2012
comment
проклятие. Спасибо за ответ. Это все еще не работает для меня. Думаю, мне придется просмотреть его еще немного - person Simon; 26.07.2012