-2

为了避免对我要删除的子元素名称进行硬编码,我想在找到匹配的父元素名称时创建一个动态过程来删除子元素。

我的 XML 文件:

<A>
    <B1>
        <C>C</C>
        <D>D</D>
        <E>E</E>
        <H>H</H>
        <MOD>
            <C>C</C>
            <D>D</D>
            <E>E</E>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B1>
    <B2>
        <C>C</C>
        <E>E</E>
        <H>H</H>
        <MOD>
            <C>C</C>
            <D>D</D>
            <E>E</E>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B2>
    <B3>
        <D>D</D>
        <E>E</E>
        <H>H</H>
        <X>X</X>
        <MOD>
            <C>C</C>
            <D>D</D>
            <E>E</E>
            <F>F</F>
            <G>G</G>
            <X>G</X>
        </MOD>
    </B3>
</A>

期望的输出:

我的 XML 文件:

<A>
    <B1>
        <C>C</C>
        <D>D</D>
        <E>E</E>
        <H>H</H>
        <MOD>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B1>
    <B2>
        <C>C</C>
        <E>E</E>
        <H>H</H>
        <MOD>
            <D>D</D>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B2>
    <B3>
        <D>D</D>
        <E>E</E>
        <H>H</H>
        <X>X</X>
        <MOD>
            <C>C</C>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B3>
</A>

我的 XSLT

     <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
            exclude-result-prefixes="xs">
    <xsl:strip-space elements="*"/>
    <!-- copy all nodes -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <!-- Remove child elements but keep parent element with same name -->
    <xsl:template match="C[../ancestor::*/C]"/>
    <xsl:template match="D[../ancestor::*/D]"/>
    <xsl:template match="E[../ancestor::*/E]"/>
</xsl:stylesheet>

我想我可以像这样组合删除元素代码

<xsl:template match="C|D|E[../ancestor::*/C|D|E]"/>

我不知道如何开始,但我认为该过程必须获取父节点名称(C、D、E、H),循环遍历将父节点名称与每个子节点名称进行比较的子节点。找到匹配项后,删除子元素。谢谢。

4

2 回答 2

1

当这个 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template
    match="MOD/*[../../* = self::* or preceding-sibling::* = self::*]"/>

</xsl:stylesheet>

...针对提供的 XML 应用:

<A>
  <B1>
    <C>C</C>
    <D>D</D>
    <E>E</E>
    <H>H</H>
    <MOD>
      <C>C</C>
      <D>D</D>
      <E>E</E>
      <F>F</F>
      <G>G</G>
    </MOD>
  </B1>
  <B2>
    <C>C</C>
    <E>E</E>
    <H>H</H>
    <MOD>
      <C>C</C>
      <D>D</D>
      <E>E</E>
      <F>F</F>
      <G>G</G>
    </MOD>
  </B2>
  <B3>
    <D>D</D>
    <E>E</E>
    <H>H</H>
    <X>X</X>
    <MOD>
      <C>C</C>
      <D>D</D>
      <E>E</E>
      <F>F</F>
      <G>G</G>
      <X>G</X>
    </MOD>
  </B3>
</A>

...产生了想要的结果:

<A>
  <B1>
    <C>C</C>
    <D>D</D>
    <E>E</E>
    <H>H</H>
    <MOD>
      <F>F</F>
      <G>G</G>
    </MOD>
  </B1>
  <B2>
    <C>C</C>
    <E>E</E>
    <H>H</H>
    <MOD>
      <D>D</D>
      <F>F</F>
      <G>G</G>
    </MOD>
  </B2>
  <B3>
    <D>D</D>
    <E>E</E>
    <H>H</H>
    <X>X</X>
    <MOD>
      <C>C</C>
      <F>F</F>
      <G>G</G>
    </MOD>
  </B3>
</A>

解释:

  • 第一个模板是众所周知的Identity Template,它将所有节点和属性从源文档复制到结果文档。
  • 第二个模板覆盖了第一个模板并有效地删除了它的所有子模板<MOD>
    • 与前一个兄弟姐妹同名或
    • 与父母的兄弟姐妹同名<MOD>(“叔叔或阿姨”)
于 2013-05-13T19:22:04.560 回答
1

据我所知,这个样式表可以满足您的需要。它通过排除具有同名同名兄弟的父元素的元素来生成与您所说的所需内容匹配的输出。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

  <xsl:strip-space elements="*"/>
  <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="*">
    <xsl:if test="not(parent::*/preceding-sibling::*[name() = name(current())])">
      <xsl:copy>
        <xsl:apply-templates/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>
于 2013-05-13T20:55:20.627 回答