2

我有一种情况,我试图通过以下方式将多个可能的路径匹配到模板:

<xsl:template match="blah">
  <xsl:apply-templates select="foo/*/baz" mode="someMode"/>
</xsl:template>

<xsl:template match="*" mode="someMode">
  <xsl:if test="current() != 'foo/bar/baz' and
                current() ! ='foo/bam/baz'">

    <!-- Process here --> 

  </xsl:if>
</xsl:template>

如您所见,“foo”下可以有任意数量的元素具有“baz”元素(例如,“bar”、“bam”、“bal”、“bav”等),但我知道大约只有 2 个,“bar”和“bam”。我不想处理这些,但我想处理其他的。不幸的是,current() 方法没有返回匹配的路径,所以测试总是成功的(即使路径是 'foo/bar/baz' 或 'foo/bam/baz'.

如何检索在 if-test 中匹配的路径?

请注意:我不能有其他专门匹配 'foo/bar/baz' 和 'foo/bam/baz' 的 xsl:template 元素,因为它们正在其他地方(以其他方式)进行处理。

4

2 回答 2

2

current函数不返回路径,它返回当前上下文节点(即在[]谓词之外它与 完全相同.,在谓词内部它是它之外的值.)。

而不是使用你应该为与你想要的特定元素匹配的<xsl:if>相同元素定义无操作模板,然后主模板只会为你想要的那些元素触发。someMode*

<xsl:template match="foo/bar/baz | foo/bam/baz" mode="someMode" />

<xsl:template match="*" mode="someMode">
  <!-- Process here -->
</xsl:template>

你这么说

请注意:我不能有其他专门匹配 'foo/bar/baz' 和 'foo/bam/baz' 的 xsl:template 元素,因为它们正在其他地方(以其他方式)进行处理。

但这就是模式的全部意义——其他foo/bar/baz模式的现有模板仍然会像以前那样做。

于 2013-03-07T19:15:43.863 回答
0

如果您有其他与 foo/bar/baz 和 foo/bam/baz 匹配的 mode="someMode" 模板,那么在该模式下匹配 * 的模板将永远不会在此类元素上触发,并且条件中的测试将始终是即使您重新制定它以说出您想要的内容,也是如此。

如果您不能完全确定与 foo/bar/baz 或 foo/bam/baz 模式匹配的给定元素是否在其他地方匹配,并且您想确保if语句中的代码不会为它触发,你可以将你的测试改写为

test="not(self::baz/parent::bar/parent::foo
          or self::baz/parent::bam/parent::foo)"

许多 XSLT 程序员会以不同的方式编写它,尽管通过在模板匹配模式的谓词中添加该测试:

<xsl:template mode="someMode" 
              match="*[not(self::baz/parent::bar/parent::foo
                      or self::baz/parent::bam/parent::foo)]">
  <!-- process ... -->
</xsl:template>
于 2013-03-07T19:17:45.060 回答