[英]how to filter out arbitrary nodes from xml document using xslt
我有一个具有以下结构的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来过滤掉所有名为junk *的元素。 也就是说,我知道我想要保留的元素名称,并且想要摆脱其他所有内容。 从上面的起点开始,所需的最终结果看起来像这样,其中所有垃圾元素都被删除了:
<?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,level1 / level2 / level3 /名称等),并希望删除其他所有内容。
到目前为止,我最好的就是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')]
结尾的所有标签//*[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)]">
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.