如何使用xslt从xml文档中筛选出任意节点



我有一个XML文件,其结构如下:

<?xml version = '1.0' encoding="ISO-8859-1"?>
<!DOCTYPE stuff PUBLIC "stuff" "stuff.dtd">
<stuff>
<level1>
<type>foo</type>
<name>name1_A</name>
<junk1>garbage</junk1>
<junk2>garbage</junk2>
<level2>
<name>name2_A</name>
<junk3>garbage</junk3>
<junk4>garbage</junk4>
<level3>
<name>name3_A</name>
<junk5>garbage</junk5>
<junk6>garbage</junk6>
</level3>
<level3>
<name>name3_B</name>
<junk5>garbage</junk5>
<junk6>garbage</junk6>
</level3>
</level2>
<level2>
<name>name2_B</name>
<junk>garbage</junk>
<level3>
<name>name3_A</name>
<junk>garbage</junk>
</level3>
<level3>
<name>name3_B</name>
<junk>garbage</junk>
</level3>
</level2>
</level1>
<level1>
<type>foo</type>
<name>name1_B</name>
<junk1>garbage</junk1>
<junk2>garbage</junk2>
<level2>
<name>name2_A</name>
<junk3>garbage</junk3>
<junk4>garbage</junk4>
<level3>
<name>name3_A</name>
<junk5>garbage</junk5>
<junk6>garbage</junk6>
</level3>
<level3>
<name>name3_B</name>
<junk5>garbage</junk5>
<junk6>garbage</junk6>
</level3>
</level2>
<level2>
<name>name2_B</name>
<junk>garbage</junk>
<level3>
<name>name3_A</name>
<junk>garbage</junk>
</level3>
<level3>
<name>name3_B</name>
<junk>garbage</junk>
</level3>
</level2>
</level1>
</stuff>

我想写一个XSLT来过滤掉所有名为垃圾*的元素。也就是说,我知道我想保留的元素名称,并且想去掉其他所有元素。以上起点的预期最终结果是这样的,去掉了所有的垃圾元素:

<?xml version = '1.0' encoding="ISO-8859-1"?>
<!DOCTYPE stuff PUBLIC "stuff" "stuff.dtd">
<stuff>
<level1>
<type>foo</type>
<name>name1_A</name>
<level2>
<name>name2_A</name>
<level3>
<name>name3_A</name>
</level3>
<level3>
<name>name3_B</name>
</level3>
</level2>
<level2>
<name>name2_B</name>
<level3>
<name>name3_A</name>
</level3>
<level3>
<name>name3_B</name>
</level3>
</level2>
</level1>
<level1>
<type>foo</type>
<name>name1_B</name>
<level2>
<name>name2_A</name>
<level3>
<name>name3_A</name>
</level3>
<level3>
<name>name3_B</name>
</level3>
</level2>
<level2>
<name>name2_B</name>
<level3>
<name>name3_A</name>
</level3>
<level3>
<name>name3_B</name>
</level3>
</level2>
</level1>
</stuff>

请记住,我的样本中的各种垃圾元素可以被命名为任何东西——我有一个我想保留的元素名称列表(例如level1/type、level1/name、level1/level2/name、level2/level3/name等),并想删除其他所有元素。

到目前为止,我得到的最好的是这个XSLT,但在这里我必须明确列出我想要删除的所有元素名称,而不是我想要保留的名称,所以它不太理想:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="no"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="junk1 | junk2 | junk3 | junk4 | junk5 | junk6"/>
</xsl:stylesheet>

如果它们的名称中有一些共同的特征,您可以将它们重新分组到不同的类别中,而不是逐个枚举要忽略的所有节点名称:

  • 所有以//*[starts-with(name(), 'junk')]开头的标签
  • //*[ends-with(name(), 'junk')]结尾的所有标签
  • 包含特定子字符串的所有标签。//*[contains(.,'junk')]

如果您不知道要删除的标记的确切名称,您可以更改XSLT的逻辑,只应用于要保留的节点的名称和复制操作。

如果您只知道要忽略的标签的名称,则使用以下逻辑:

如果您所说的"节点"是指元素,则使用:

<xsl:template match="*[not(self::ServiceNode)]">

如果"节点"是指任何节点(元素、文本、注释、处理指令类型):使用

<xsl:template match="node()[not(self::ServiceNode)]">

如果您只想匹配Document的子项,请使用:

<xsl:template match="Document/node()[not(self::ServiceNode)]">

如果您只想匹配顶部元素的子元素,请使用:

<xsl:template match="/*/node()[not(self::ServiceNode)]">

如何编写一个xpath来匹配除特定元素之外的所有元素

最新更新