如何使用xslt

时间:2017-11-07 05:40:34

标签: xml 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 / 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>

1 个答案:

答案 0 :(得分:0)

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

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

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

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

如果“node”表示元素,则使用:

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

如果“node”表示任何节点(类型为元素,文本,注释,处理指令):使用

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

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

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

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

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

How to write a xpath to match all elements except a particular element