【问题标题】:Omit input parts in XSLT except matching在 XSLT 中省略除匹配之外的输入部分
【发布时间】:2016-10-06 07:03:56
【问题描述】:

我现在对 XSL 还很陌生。

假设我有一个输入

<?xml version="1.0" encoding="UTF-8"?>
<Doc>
<A>A</A>
<B>B</B>
<C>C</C>
</Doc>

并通过 XSLT 传递它,如下所示:

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

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

<xsl:template match="A">
    <xsl:element name="Info">This is an <xsl:value-of select="."/></xsl:element>
    <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>

我会得到

<?xml version="1.0" encoding="UTF-8"?>
<Info>This is an A</Info>A
B
C

假设有一些复杂的树,我怎么能摆脱这些额外的 A 和其他 B 和 C,我怎么能说只转换模板中匹配的元素,而忽略其他所有内容?

提前致以诚挚的问候和感谢

【问题讨论】:

  • 请对不能解决您问题的答案发表评论,为确实解决您问题的答案投票,并接受您认为最有用的答案。不提供任何反馈都是不礼貌的。
  • 好的,我再问一次:是什么让您无法对收到的有用答案进行投票并将其中一个标记为已接受?

标签: xml xslt transformation


【解决方案1】:

您看到的额外输出是 XSLT 的内置标准规则的效果。

这些说:“遍历输入树并处理每个节点。对于元素节点,处理它们的子节点,对于文本节点,将它们的内容复制到输出。”

另见more in-depth explanation #1more in-depth explanation #2,当然还有the spec

只要没有处理特定节点的规则(即模板),这些标准规则就会生效。

这就是这里发生的事情:

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

上面写着:“匹配根节点并处理(即应用模板)任何子元素。”

这将处理根节点,并继续处理根节点的唯一子节点 - 文档元素&lt;Doc&gt;。之后,处理器继续处理 子级。 &lt;A&gt; 有一个自定义模板,但&lt;B&gt;&lt;C&gt; 没有自定义模板,这意味着将使用默认规则,其文本内容将在输出中结束。

请注意,这也意味着上述模板是一个空操作,可以安全地完全丢弃,而不会对结果进行任何更改。它只是重复了默认规则无论如何都会做的事情。

出路:

  • 制作一个匹配&lt;B&gt;&lt;C&gt; 的自定义模板并且不产生任何输出:

    <xsl:template match="B | C" />
    
  • 制作一个匹配任何元素节点并且不产生输出的自定义模板:

    <xsl:template match="*" />
    

    这是因为匹配表达式的特殊性。更具体的匹配表达式将优先于不太具体的匹配表达式,因此即使match="*" 也匹配&lt;A&gt;,具有match="A" 的模板将是首选。

  • 首先不要在处理的节点中包含&lt;B&gt;&lt;C&gt;

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

    注意match="/" 匹配根节点,而match="/*" 匹配文档元素(如上所述,有区别)。您可以使用match="/Doc",它比/* 更具体。但是,/* 是表达“文档元素,无论它可能被称为什么”的常用约定。

这三种策略都是有效的,这取决于你想使用哪一种情况和你的偏好。

【讨论】:

  • 非常感谢您的回答。他们解决了我的问题。问候
【解决方案2】:

这是因为 XSLT 的 built-in template rules

有多种方法可以覆盖内置规则,例如添加一个与text() 匹配的空 xsl:template。

不过,在您的具体情况下,我可能会在模板中添加一个选择以匹配根元素 (/*) 的 xsl:apply-templates,并从匹配@987654324 的模板中删除 xsl:apply-templates @...

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

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

<xsl:template match="A">
    <xsl:element name="Info">This is an <xsl:value-of select="."/></xsl:element>
</xsl:template>

</xsl:stylesheet>

另外请注意,如果您正在创建一个新元素,则您没有必须使用 xsl:element,除非您正在动态创建名称。直接输出就行了……

<Info>This is an <xsl:value-of select="."/></Info>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-11
    • 2012-11-06
    • 2018-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多