将谓词应用于当前节点

时间:2015-01-21 14:46:15

标签: xslt xpath xpath-1.0

(我发布这个自我回答的问题,因为这个问题的典型解决方案是不必要的冗长,我想直接设置记录。我找不到现有的SO问题,但如果有,请将其作为副本关闭。)

我正在寻找一种方法来执行XPath选择,只有当它符合某个条件时才选择当前节点。这将是有用的,例如,当我想有条件地将XSLT模板应用于当前节点时:

<xsl:template match="Device">
  <div>
    <h2><xsl:value-of select="Name" /></h2>
    <xsl:apply-templates select="???[Featured = 'true']" mode="featured" />
    <p><xsl:value-of select="Description" /></p>
  </div>
</xsl:template>

<xsl:template match="Book">
  <div>
    <h2><xsl:value-of select="Title" /></h2>
    <xsl:apply-templates select="???[FeaturedBook = 'true']" mode="featured" />
    <h3><xsl:value-of select="Author" /></h3>
    <p><xsl:value-of select="Summary" /></p>
  </div>
</xsl:template>

<xsl:template match="node()" mode="featured">
  <p class='featured-notice'>This is a featured item!
    <a href="/AddToCart?productId={Id}">Buy now</a> to get a 15% discount.
  </p>
</xsl:template>

我尝试过使用.[Featured = 'true'],但是我遇到了语法错误。我怎么能这样做?

我不会在这里添加输入和输出,因为它们与问题相关并且会使它非常长,但是如果你想看到我的想法,我把它们放在这里: inputoutput

2 个答案:

答案 0 :(得分:10)

由于语法规则,XPath 1.0中不允许使用语法.[predicate](有关详细信息,请参阅本文末尾)。

我发现的100%建议说唯一的选择就是使用self::node()

self::node()[Featured = 'true']

This XPath tester甚至专门设计用于告知用户self::node()[predicate]如果他们尝试使用.[predicate],但这不是唯一的选择。

一个有效且更简洁的选项是将缩写步骤包装在括号中:

(.)[Featured = 'true']

XPath 1.0语法规则完全有效(在我看来,更清晰)。

您也可以使用..缩写步骤使用此方法,甚至可以使用多个级别:

Select grandfather node if it is featured


../..[Featured = 'true']                - Not valid

../../../*[Featured = 'true']           - Valid, but not accurate

../../self::node()[Featured = 'true']   - Valid, but verbose

(../..)[Featured = 'true']              - Valid

<小时/> 附录:为什么在XPath 1.0中无法使用.[predicate]

以下是XPath 1.0中“步骤”的定义(基本上,由斜杠分隔的XPath节点选择表达式的部分称为“步骤”):

  

[4] Step :: = AxisSpecifier NodeTest Predicate * | AbbreviatedStep

这意味着一步包含两个可能的选项之一:

  • 轴说明符(可以是空字符串),后跟节点测试,后跟0或更多谓词
  • 缩略步骤:...

没有选项可以使用缩写步骤后跟谓词。

答案 1 :(得分:-1)

<xsl:template match="Device">
  <div>
    <h2><xsl:value-of select="Name" /></h2>
    <xsl:apply-templates select="Featured[. = 'true']" />
    <p><xsl:value-of select="Description" /></p>
  </div>
</xsl:template>

<xsl:template match="Book">
  <div>
    <h2><xsl:value-of select="Title" /></h2>
    <xsl:apply-templates select="FeaturedBook[. = 'true']" />
    <h3><xsl:value-of select="Author" /></h3>
    <p><xsl:value-of select="Summary" /></p>
  </div>
</xsl:template>

<xsl:template match="FeaturedBook|Featured">
  <p class='featured-notice'>This is a featured item!
    <a href="/AddToCart?productId={Id}">Buy now</a> to get a 15% discount.
  </p>
</xsl:template>