嵌套在不需要的元素中的XSLT选择所需元素

时间:2009-06-18 00:51:02

标签: xslt

当要提取的节点有时候被忽略的嵌套节点时,我会使用什么XSLT来提取一些节点来输出,忽略其他节点?

考虑:

<alpha_top>This prints.
  <beta>This doesn't.
    <alpha_bottom>This too prints.</alpha_bottom>
  </beta>
</alpha_top>

我想要一个产生的变换:

<alpha_top>This prints.
    <alpha_bottom>This too prints.</alpha_bottom>
</alpha_top>

answer显示如何根据元素标记名称中字符串的存在来选择节点。

4 个答案:

答案 0 :(得分:0)

以下样式表适用于您的特定情况,但我怀疑您正在寻找更通用的东西。我也确信有一种更简单的方法。

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
    <xsl:apply-templates select="alpha_top"></xsl:apply-templates>
</xsl:template>

<xsl:template match="alpha_top">
    <xsl:copy>
    <xsl:apply-templates select="beta/alpha_bottom|text()"></xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="*|text()">
    <xsl:copy>
        <xsl:apply-templates select="*|text()"></xsl:apply-templates>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

好的,这是一个更好的方法

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="beta">
    <xsl:apply-templates select="*"></xsl:apply-templates>
</xsl:template>

<xsl:template match="/|*|text()">
    <xsl:copy>
        <xsl:apply-templates select="*|text()"></xsl:apply-templates>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

这基本上是一个身份变换,但是对于你不想要包含的元素,我删除了xsl:copy并仅在子元素上应用了模板。

答案 2 :(得分:0)

我认为,一旦你对XSLT遍历的工作方式有了合理的理解(希望我在你的另一个问题中回答),这就变得非常简单了。

您有多种选择可以做到这一点。 Darrell Miller的回答显示你必须处理整个文档并删除你不感兴趣的元素。这是一种方法。

在我走得更远之前,我得到的印象是你可能不会完全“理解”XSLT中的上下文概念。这很重要,会让您的生活更加简单。在XSLT中的任何时候都有一个唯一的上下文节点。这是当前正在“处理”的节点(元素,属性,注释等)。在通过xsl调用的模板内:选择已选择的节点是上下文节点。所以,给你的xml:

<alpha_top>This prints.
  <beta>This doesn't.
    <alpha_bottom>This too prints.</alpha_bottom>
  </beta>
</alpha_top>

以及以下内容:

<xsl:apply-templates select='beta'/>

<xsl:template match='beta'>...</xsl:template>

beta节点将是模板内的上下文节点。还有更多的东西,但不多。

因此,当您使用类似以下内容开始样式表时

<xsl:template match='/'>
    <xsl:apply-templates select='alpha_top'/>
</xsl:apply-templates>

您正在选择文档节点的子节点(唯一的子元素是alpha_top元素)。你里面的xpath语句是相对于上下文节点的。

现在,在该顶级模板中,您可能决定只想处理alpha_bottom节点。然后你可以发表一个声明:

<xsl:template match='/>
    <xsl:apply-templates select='//alpha_top'/>
</xsl:template>

这将沿着树向下走,并选择所有alpha_top元素,而不是其他任何内容。

或者,您可以处理所有元素,只需忽略测试节点的内容:

<xsl:template match='beta'>
    <xsl:apply-templates/>
</xsl:template>

(正如我在其他回复中提到的那样xsl:apply-templates没有select属性与使用 select =''*)相同。

这将忽略测试节点的内容,但会处理其所有子节点(假设您有模板)。

因此,忽略输出中的元素基本上是在select属性中使用正确的xpath语句。当然,您可能需要一个好的xpath教程:)

答案 3 :(得分:0)

对您的问题最简单的解决方案是:

<xsl:template match="alpha_top|alpha_bottom">
  <xsl:copy>
    <xsl:value-of select="text()" />
    <xsl:apply-templates />
  </xsl:copy>
</xs:template>

<xsl:template match="text()" />

这与您的示例中没有相同的空白行为,但这可能无关紧要。