从xml中删除所有节点,使用XSLT排除特定节点

问题描述:

我有一堆xml文件,其中有不同数量的节点,我想使用XSLT更改文件以仅包含特定节点。 例子:从xml中删除所有节点,使用XSLT排除特定节点

<?xml version="1.0" encoding="UTF-8"?> 
<SomeName> 
<identifier> 
    <UID> 1234 </UID> 
</identifier> 
<MainNode1> 
    <SubNode1> 
     <Subnode1a>DATA1a0</Subnode1a> 
    </SubNode1> 
    <SubNode1> 
     <Subnode1a>DATA1a1</Subnode1a> 
    </SubNode1> 
    <SubNode1> 
     <Subnode1a>DATA1a2</Subnode1a> 
    </SubNode1> 
    </MainNode1> 

    <MainNode2> 
    <SubNode2> 
     <Subnode2a>DATA2a0</Subnode2a> 
    </SubNode2> 
    </MainNode2> 

    <MainNodeIDONTCARE> 
     <SubnodeWhatever> 
     </SubnodeWhatever> 
    </MainNodeIDONTCARE> 

    <MainNodeuseless> 
     <SubnodeWhatever> 
     </SubnodeWhatever> 
    </MainNodeuseless> 

    <MainNodewhatever> 
     <SubnodeWhatever> 
     </SubnodeWhatever> 
    </MainNodewhatever> 
</SomeName> 

现在我的最后的XML文件看起来应该像:

<?xml version="1.0" encoding="UTF-8"?> 
<SomeName> 
<identifier> 
    <UID> 1234 </UID> 
</identifier> 
<MainNode1> 
    <SubNode1> 
     <Subnode1a>DATA1a0</Subnode1a> 
    </SubNode1> 
    <SubNode1> 
     <Subnode1a>DATA1a1</Subnode1a> 
    </SubNode1> 
    <SubNode1> 
     <Subnode1a>DATA1a2</Subnode1a> 
    </SubNode1> 
    </MainNode1> 

    <MainNode2> 
    <SubNode2> 
     <Subnode2a>DATA2a0</Subnode2a> 
    </SubNode2> 
    </MainNode2> 
</SomeName> 

我一直在试图把它与XSLT做,但我似乎无法完成它。

感谢您的任何帮助。

+0

好问题(+1)。请参阅我的答案,了解最简单的解决方案,它也完全符合XSLT的精神,并且不使用任何''指令。 :) – 2010-05-26 16:55:17

这应该工作:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="SomeName"> 
    <xsl:copy> 
     <xsl:for-each select="identifier|MainNode1|MainNode2"> 
     <xsl:copy> 
      <xsl:apply-templates /> 
     </xsl:copy> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

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

</xsl:stylesheet> 

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

    <xsl:template match="SomeName"> 
    <xsl:copy> 
     <xsl:for-each select="identifier|MainNode1|MainNode2"> 
     <xsl:apply-templates select="." /> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

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

根据OP的要求,不包括标识符,MainNode1,MainNode2。 – AxelEckenberger 2010-05-26 16:38:13

+0

@Obalix:感谢您的评论,我以我自己的方式纠正了错误。 您的解决方案也很好。 – Gart 2010-05-26 16:44:35

可能最短的解决方案是以下

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<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="MainNodeIDONTCARE | MainNodeuseless | MainNodewhatever"/> 
</xsl:stylesheet> 

当这种变换的应用提供了XML文档,wante d产生输出

<SomeName> 
    <identifier> 
     <UID> 1234 </UID> 
    </identifier> 
    <MainNode1> 
     <SubNode1> 
      <Subnode1a>DATA1a0</Subnode1a> 
     </SubNode1> 
     <SubNode1> 
      <Subnode1a>DATA1a1</Subnode1a> 
     </SubNode1> 
     <SubNode1> 
      <Subnode1a>DATA1a2</Subnode1a> 
     </SubNode1> 
    </MainNode1> 
    <MainNode2> 
     <SubNode2> 
      <Subnode2a>DATA2a0</Subnode2a> 
     </SubNode2> 
    </MainNode2> 
</SomeName> 

请注意,使用了最根本的XSLT设计模式:使用并重写身份规则

+0

只有当你知道所有要丢弃的元素 – Gart 2010-05-26 17:27:53

+0

@Gart时,该解决方案才是有效的:是的,OP没有明确指出他是否希望除了某些已知元素以外的所有元素都被丢弃,或者如果他希望除了某些已知元素元素。 – 2010-05-26 18:55:55

+0

这真的是我需要的。当结构发生变化时,更容易排除新节点,而不必更新所有节点作为副本的XLST。 – 2ndkauboy 2011-12-15 14:32:38