xpath 2.0按属性选择元素

时间:2012-07-26 12:12:57

标签: xpath xslt-2.0 xpath-2.0

我一直在xpath 1.0中使用以下xpath选择

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

这非常有效,完全符合我的要求。 但是我开始将XSLT 2.0与xPath 2.0结合使用,这不再适用 (使用Altova XML处理器) 我收到以下错误:

  

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 - =

大致翻译为:

  

无法设置为target-type - 当前元素为'sid-B3FD7EE5-043   类型为xs的3-4939-A69F-E74B30FDEB1C':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>

2 个答案:

答案 0 :(得分:1)

我无法重现这个问题。

此转化

<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

答案 1 :(得分:1)

我想知道你是否有一个模式将@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进行比较可能会失败并显示类似于引用的消息