我有
<?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”, 我该如何解决这种情况?
答案 0 :(得分:2)
请将此模板添加到您的XSLT:
<xsl:template match="text()"/>
,您的输出将如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<sect1 label="">
<title>Test1 Section</title>
<para>Some content</para>
</sect1>
我认为这是想要的输出?
祝你好运, 彼得
答案 1 :(得分:1)
XSLT对所有节点都有默认built-in template rules,如果您没有指定显式模板,则适用。处理始终通过将模板应用于文档根节点开始,元素的默认规则仅为
<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>
直接跳到您感兴趣的部分,不将默认模板应用到其他元素。