重构XPath表达式:仅指定一次子表达式

时间:2016-11-21 06:10:10

标签: xslt xpath xpath-2.0

我想总结指定为test指令的<xsl:if>属性的XPath表达式的子表达式,它可能在我的xslt中多次出现(并作为不同Xpath表达式的一部分)样式表。例如:

<xsl:if test="
  preceding-sibling::node()[
  (self::a and @attr1='a1') or
  (self::b and @attr2='b1')
  ] or
  following-sibling::node()[
  (self::a and @attr1='a1') or
  (self::b and @attr2='b1')
  ]
">
...
</xsl:if>

正如您所看到的,子表达式(self::a and ...)被重复,但应用谓词的节点可能会有所不同。

3 个答案:

答案 0 :(得分:0)

所以,对你剩下的XSLT以及你正在解决的任务一无所知,你当前的表达式可以被压缩成

<xsl:if test="
  preceding-sibling::a/@attr1='a1' or
  preceding-sibling::b/@attr2='b1' or
  following-sibling::a/@attr1='a1' or
  following-sibling::b/@attr2='b1'
">
...
</xsl:if>

注释

  • (a or b) or (c or d)相当于a or b or c or d
  • preceding-sibling::node()还可以选择文本节点,注释等。如果您要选择元素,则使用node()将不正确。
  • preceding-siblingfollowing-sibling指的是所有这样的兄弟姐妹。 following-sibling::a/@attr1='a1'会测试以下任何名为a的兄弟是否有attr1="a1" 如果您只是指紧接着的兄弟姐妹,请使用following-sibling::a[1]

答案 1 :(得分:0)

如果您的处理器支持功能,例如exsl:函数然后你可以使用

<fx:function name="my:testcondition">
    <xsl:param name="testnode"/>
    <fx:result select="$testnode/a/@attr1 = 'a1' or $testnode/b/@attr2 = 'b1'"/>
</fx:function>

您可能必须在exsl:node-set()周围使用$testnode,并为函数使用一些名称空间为my的命名空间。

然后你可以写

<xsl:if test="preceding-sibling::node()[my:testcondition(.)] or following-sibling::node()[my:testcondition(.)]">

现在我看到你xslt-2.0标签,这可能是可能的,但我自己也不能给你详细信息......: - (

答案 2 :(得分:0)

XPath 2.0:

  ../(* except .)
        [(self::a and @attr1='a1') 
        or
         (self::b and @attr2='b1')
         ]

XSLT 2.0使用 <xsl:function>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:function name="my:myFilter" as="node()*">
    <xsl:param name="pContext" as="node()"/>
      <xsl:sequence select=
       "$pContext/../(* except $pContext)
        [(self::a and @attr1='a1') 
        or
         (self::b and @attr2='b1')
         ]"/>
  </xsl:function>
</xsl:stylesheet>

定义了上面的函数,可以将它作为XPath表达式的一部分来调用

my:myFilter(.)

XSLT 1.0 / XPath 1.0

  ../*[count(.|current()) = 2]
        [(self::a and @attr1='a1') 
        or
         (self::b and @attr2='b1')
         ]