【问题标题】:Check any level of parent nodes with XPath and XSLT使用 XPath 和 XSLT 检查任何级别的父节点
【发布时间】:2014-12-05 14:34:39
【问题描述】:

我已经搜索过,但可能只是因为我不知道要搜索什么而错过了一些明显的东西。而且我发现很难将我的问题解释为一个简单的问题,所以让我解释一下:我正在使用以下代码(XSLT 1.0 和 XPath)来检查该节点的父节点是否属于最后一个祖父节点:

<xsl:when test="count(parent::*/preceding-sibling::*)+1 = count(parent::*/parent::*/*)">

它完全符合我的要求。不过,我希望以一种或另一种方式使其更通用,以使其与更多父节点一起使用。我可以添加另一个模板匹配并添加另一个测试:

<xsl:when test ="count(parent::*/parent::*/preceding-sibling::*)+1 = count(parent::*/parent::*/*)">

有没有办法在递归模板循环中添加“parent::*/”而不是创建很多特定的模板匹配?还是我应该完全编写出更好的 XPath 代码?

请注意:我想检查每个级别的父节点。父母是父母中的最后一位吗,祖父母是祖父母中的最后一位,等等。

为了清楚起见,我这样使用它:

<xsl:choose>
  <xsl:when test="count(parent::*/preceding-sibling::*)+1 = count(parent::*/parent::*/*)">
    <!-- show image A -->
  </xsl:when>
  <xsl:otherwise>
    <!-- show image B -->
  </xsl:otherwise>
</xsl:choose>

【问题讨论】:

  • 使用祖先:: 轴而不是父:: ?
  • @Mike 我去查一下,乍一看好像是我想要的。
  • 嗯,不,这不是我真正想要的,因为我想知道每个祖先是否是最后一个,而不是所有祖先。

标签: xslt xpath


【解决方案1】:
<xsl:when test="count(parent::*/preceding-sibling::*)+1 = count(parent::*/parent::*/*)">

可以简化为:

<xsl:when test="not(../following-sibling::*)">

用简单的英语“我的父母没有跟随元素兄弟”


这很容易修改为:

<xsl:when test="not(../../following-sibling::*)">

用简单的英语“我父母的父母没有跟随元素兄弟”。等等。


同时检查所有祖先:

<xsl:when test="not(ancestor::*/following-sibling::*)">

用简单的英语“我的祖先没有一个跟随元素兄弟”


同时检查父母和祖父母:

<xsl:when test="not(ancestor::*[position() &lt;= 2]/following-sibling::*)">

用简单的英语“我的两个最亲近的祖先中没有一个有以下元素兄弟”


编辑要单独检查所有祖先,请使用递归模板(优点:内部&lt;xsl:apply-templates&gt; 的位置决定了您是否有效地在祖先列表中向上或向下):

<xsl:template match="*" mode="line-img">
  <xsl:if test="following-sibling::*">
    <!-- show image A -->
  </xsl:if>
  <xsl:if test="not(following-sibling::*)">
    <!-- show image B -->
  </xsl:if>
  <xsl:apply-templates select=".." mode="line-img" />
</xsl:template>

<!-- and later... -->

<xsl:apply-templates select=".." mode="line-img" />

...或一个简单的 for-each 循环(始终按文档顺序工作):

<xsl:for-each select="ancestor::*">
  <xsl:if test="following-sibling::*">
    <!-- show image A -->
  </xsl:if>
  <xsl:if test="not(following-sibling::*)">
    <!-- show image B -->
  </xsl:if>
</xsl:for-each>

...或者,完全地道(总是按文档顺序工作):

<xsl:template match="*" mode="line-img">
  <xsl:if test="following-sibling::*">
    <!-- show image A -->
  </xsl:if>
  <xsl:if test="not(following-sibling::*)">
    <!-- show image B -->
  </xsl:if>
</xsl:template>

<!-- and later... -->

<xsl:apply-templates select="ancestor::*" mode="line-img" />

【讨论】:

  • 第一部分很有意义,而且非常有用!不过,我在第一篇文章中有点不清楚,因为我需要对每个祖先进行单独检查。
  • 我猜其他变种之一会做你想要的?
  • 不是真的,如果我理解正确的话。但是使用“not(../following-sibling::*)”简化以及将父节点作为参数发送的递归模板可能会做我想要的,因为我需要每个祖先的测试结果,比如:“是,不,不,是,不”例如。
  • @timlarsson 啊,您需要分别每个结果。那么是的,递归模板是要走的路。 (请问为什么?)
  • 完美! :) 很抱歉我在主帖中不够清楚,但是当您不是以英语为母语的人,也不太熟悉 XPath 和 XSLT 时,很难清楚地表达自己 :) 如果我我会 +1可以,但我还不允许。
猜你喜欢
  • 1970-01-01
  • 2017-03-14
  • 2011-04-10
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多