4

(我发布这个自我回答的问题是因为通常为这个问题提供的解决方案是不必要的冗长,我想澄清一下。我找不到现有的 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

4

2 回答 2

14

由于.[predicate]语法规则,该语法在 XPath 1.0 中是不允许的(请参阅本文末尾的详细信息)。

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

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

这个 XPath 测试器甚至专门设计用来告诉用户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


附录:为什么不能.[predicate]在 XPath 1.0中使用

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

[4] 步骤 ::= AxisSpecifier 节点测试谓词* | 缩写步骤

这意味着一个步骤由两个可能的选项之一组成:

  • 轴说明符(可以是空字符串),后跟节点测试,后跟 0 个或多个谓词
  • 一个简短的步骤:...

没有选项可以让缩写的步骤后跟谓词。

于 2015-01-21T14:46:15.310 回答
-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>
于 2015-01-22T10:44:48.770 回答