繁体   English   中英

如何使用xslt从xml文档中过滤掉任意节点

[英]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)]">

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM