逗号分隔的自我和后续兄弟的表达式列表在XPath中工作,但不作为XSLT匹配模式

时间:2016-08-14 06:56:49

标签: xml xslt xpath xslt-2.0 xpath-2.0

这是一个有效的XPath 2.0:

//hi[@rend="bold"]/(self::hi, following-sibling::*, following-sibling::text())

它选择具有给定属性的所有hi节点以及所有兄弟元素和文本节点。

但是,如果我尝试在XSLT 2.0中使用此XPath:

<xsl:template match="hi[@rend='bold']/(self::hi, following-sibling::*, following-sibling::text())">
        <!--do something-->
    </xsl:template>

我收到语法错误。这是为什么?如何重写此匹配模式以便它在XSLT中工作?

目标是能够将所有上述内容包装在新元素中。

一切顺利, 丁鲷

3 个答案:

答案 0 :(得分:2)

我有时会处于我想要将模板规则应用于由这样的复杂模式选择的节点的位置,并且最好的解决方案是将全局变量绑定到所有相关节点然后使用模式中的全局变量:

<xsl:variable name="afterBold"
  select="//hi[@rend="bold"]/
   (self::hi, following-sibling::*, following-sibling::text())"/>

<xsl:template match="node()[. intersect $afterBold]"/>

以上需要XSLT 2.0。在XSLT 3.0中,它可以简化:

<xsl:template match="$afterBold"/>

答案 1 :(得分:1)

  

我收到语法错误。那是为什么?

XSLT 匹配模式拥有自己的syntax rules。只有有效XPath表达式的子集也是有效的匹配模式。

  

如何重写此匹配模式以便它在XSLT中工作?

脱离我的头顶:

<xsl:template match="hi[@rend='bold'] | *[preceding-sibling::hi[@rend='bold']] | text()[preceding-sibling::hi[@rend='bold']]">

可能有更优雅的方式表达它,但我相信它符合你所说的你想做的事。

答案 2 :(得分:0)

这就是我设法解决上述问题的方法:

scala> p1.show()
+--------+-----------------+
|area_tag|              vin|
+--------+-----------------+
|        |LSKG5GC19BA210794|
|        |LSKG5GC15BA210372|
|        |LSKG5GC18BA210107|
|        |LSKG4GC16BA211971|
|        |LSKG4GC19BA210233|
|        |LSKG5GC17BA210017|
|        |LSKG4GC19BA211785|
|        |LSKG4GC15BA210004|
|        |LSKG4GC12BA211739|
|        |LSKG4GC18BA210238|
|        |LSKG4GC13BA210261|
|        |LSKG5GC16BA210106|
|        |LSKG4GC1XBA210287|
|        |LSKG4GC10BA210265|
|        |LSKG5GC10CA210118|
|        |LSKG5GC16BA212289|
|        |LSKG5GC1XBA211016|
|        |LSKG5GC15CA210194|
|        |LSKG5GC12CA210119|
|        |LSKG4GC19BA211379|
+--------+-----------------+
only showing top 20 rows

基本上,我们首先匹配hi元素,将其包装并复制其后续节点;在一个单独的模式中,我们匹配具有特定hi元素的节点作为它们的前一个兄弟,以便它们的内容在输出中不会出现两次。

一个重要的经验教训:你不能只接受任何xPath并将其粘贴在你的XSLT中。