1

我有

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<article lang="en">
     <articleinfo>
            <title>Test Article</title>
     </articleinfo>
     <sect1 label="">
            <title>Test1 Section</title>
            <para>Some content</para>
    </sect1>
    <sect1>
            <title>Test2 Section</title>
            <para>Another content</para>
    </sect1>
</article>

我只想提取一个标题为“Test1”的sect1,所以我写了这样简单的xsl转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:d="http://docbook.org/ns/docbook">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="article/sect1[contains(title, 'Test1')]">
  <xsl:message>Match</xsl:message>
  <xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

但是由于某些未知的原因,这种转换不仅复制了带有上述标题的 sect1,而且还复制了所有 XML 文件减去标签的内容:

xsltproc ./extract_sect1.xsl test.xml 
Match
<?xml version="1.0"?>


            Test Article

    <sect1 label="">
            <title>Test1 Section</title>
            <para>Some content</para>
    </sect1>

            Test2 Section
            Another content

所以问题,为什么我得到“Test2 Section”和“Another content”,我该如何解决这种情况?

4

2 回答 2

2

请将此模板添加到您的 XSLT:

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

您的输出将如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<sect1 label="">
    <title>Test1 Section</title>
    <para>Some content</para>
</sect1>
于 2013-09-05T14:41:01.657 回答
1

XSLT 具有适用于所有节点的默认内置模板规则,如果您未指定显式模板,则这些规则适用。处理总是从将模板应用到文档根节点开始,元素的默认规则是

<xsl:apply-templates/>

(即继续递归地将模板应用到子节点)。您的问题是文本节点的默认模板规则是将文本输出到结果树。因此,对于除 之外的所有节点,article/sect1[contains(title, 'Test1')]您将获得所有后代文本节点输出到结果。

有两种明显的方法可以解决这个问题,您可以定义

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

抑制默认文本节点行为,或者添加

<xsl:template match="/">
  <xsl:apply-templates select="article/sect1[contains(title, 'Test1')]" />
</xsl:template>

直接跳转到您感兴趣的部分,并且根本不将默认模板应用于其他元素。

于 2013-09-05T14:53:17.990 回答