2011-03-21 120 views
1

是否有人知道如何使用xslt进行以下转换?如何使用xslt删除xml中的某些节点?

的源代码:

<?xml version="1.0" encoding="UTF-8"?> 
<body> 
    <termEntry id="1"> 
    <langSet lang="eng-us"> 
    <ntig> 
    <termGrp> 
     <term></term> 
    </termGrp> 
    </ntig> 
    <ntig> 
    <termGrp> 
     <term></term> 
    </termGrp> 
    </ntig> 
    </langSet> 

    <langSet lang="ara-ae"> 
    <ntig> 
    <termGrp> 
     <term>123</term> 
    </termGrp> 
    </ntig> 
    </langSet> 
</termEntry> 

<termEntry id="2"> 
<langSet lang="eng-us"> 
    <ntig> 
    <termGrp> 
    <term></term> 
    </termGrp> 
    </ntig> 
    <ntig> 
    <termGrp> 
    <term></term> 
    </termGrp> 
    </ntig> 
    <ntig> 
    <termGrp> 
    <term>123</term> 
    </termGrp> 
    </ntig> 
</langSet> 
</termEntry> 
</body> 

请求: 1.如果在<term></term>值为null \空,删除其祖父节点,即

<ntig></ntig> 

2.In这样,如果所有<term>标签都为空,则删除整个<langset>节点。

预期的结果

<?xml version="1.0" encoding="UTF-8"?> 
<body> 
    <termEntry id="1"> 

    <langSet lang="ara-ae"> 
    <ntig> 
    <termGrp> 
     <term>123</term> 
    </termGrp> 
    </ntig> 
    </langSet> 
    </termEntry> 

    <termEntry id="2"> 
    <langSet lang="eng-us"> 
    <ntig> 
    <termGrp> 
     <term>123</term> 
    </termGrp> 
    </ntig> 
    </langSet> 
</termEntry> 
</body> 
+0

好问题,+1。查看我的解决方案,获得一个完整,简短和简单的解决方案,与其他答案不同,严格执行问题的要求。 :) – 2011-03-21 13:05:49

回答

3

身份变换加上一些简单的空模板是什么您这里需要。你想把所有的输入复制到输出中,除非它符合你的标准,在这种情况下你想压制它。

一个样式,例如:

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

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

    <xsl:template match="ntig[descendant::term[. = '']]"/> 
    <xsl:template match="langSet[not(descendant::term[. != ''])]"/> 

</xsl:stylesheet> 

会做你的需要。匹配ntig元素的模板将禁止那些元素为空的term孙子。与langSet元素相匹配的模板会抑制那些不存在具有内容的子元素termlangSets

+0

嗨尼克,我想通过添加'<?xml-stylesheet type =“text/xsl”href =“FM_Nic.xsl”?>'然后单击xml,仅显示文本值** 123 123 **而不是预期的代码...我是否需要添加更多的参考? – mj023119 2011-03-22 02:46:21

+0

顺便说一句,我不知道我是否可以生成新的XML而不是查看。如何?通过** not **使用其他编程语言,比如说java – mj023119 2011-03-22 02:52:25

+0

@Jackie - 请参阅@ Dimitre的答案,为您解释为什么会发生这种情况。 – 2011-03-22 08:38:04

1

该转化

<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="ntig[not(*/term[string-length()>0])]"/> 
<xsl:template match="langSet[not(*/*/term[string-length()>0])]"/> 
</xsl:stylesheet> 

当所提供的XML文档施加:

<body> 
    <termEntry id="1"> 
     <langSet lang="eng-us"> 
      <ntig> 
       <termGrp> 
        <term></term> 
       </termGrp> 
      </ntig> 
      <ntig> 
       <termGrp> 
        <term></term> 
       </termGrp> 
      </ntig> 
     </langSet> 
     <langSet lang="ara-ae"> 
      <ntig> 
       <termGrp> 
        <term>123</term> 
       </termGrp> 
      </ntig> 
     </langSet> 
    </termEntry> 
    <termEntry id="2"> 
     <langSet lang="eng-us"> 
      <ntig> 
       <termGrp> 
        <term></term> 
       </termGrp> 
      </ntig> 
      <ntig> 
       <termGrp> 
        <term></term> 
       </termGrp> 
      </ntig> 
      <ntig> 
       <termGrp> 
        <term>123</term> 
       </termGrp> 
      </ntig> 
     </langSet> 
    </termEntry> 
</body> 

产生想要的结果

<body> 
    <termEntry id="1"> 
     <langSet lang="ara-ae"> 
     <ntig> 
      <termGrp> 
       <term>123</term> 
      </termGrp> 
     </ntig> 
     </langSet> 
    </termEntry> 
    <termEntry id="2"> 
     <langSet lang="eng-us"> 
     <ntig> 
      <termGrp> 
       <term>123</term> 
      </termGrp> 
     </ntig> 
     </langSet> 
    </termEntry> 
</body> 

说明

  1. 身份规则(模板)副本的每个节点 “原样”。

  2. 模板重写身份规则ntig[not(*/term[string-length()>0])]有一个空的身体 - 这有效地忽略(删除)不具有在免得一个term孙子正string-length()任何ntig元素。

  3. 模板重写身份规则langSet[not(*/*/term[string-length()>0])]有一个空的身体 - 这有效地忽略(删除)不具有在免得一个term曾孙正string-length()任何langSet元素。

请注意当指定这样的模板违反了问题的定义:

<xsl:template match="ntig[descendant::term[. = '']]"/> 
<xsl:template match="langSet[not(descendant::term[. != ''])]"/> 

因为要求是“如果该值为null \空,删除其祖父节点”。

然而,第一个模板上面不仅有盛大的父母ntig,但删除任何祖先ntig

目前的解决方案没有犯这样的错误

+0

@Dimitre:嗨Dimitre,我想通过添加'<?xml-stylesheet type =“text/xsl”href =“FM_Dimi.xsl”?>'然后单击xml,只显示文本值** 123 123 **而不是预期的代码...我是否需要添加更多参考?顺便说一下,我想知道是否可以生成新的XML而不是查看。如何?通过** not **使用其他编程语言,比如java – mj023119 2011-03-22 02:51:03

+0

@Jackie:这是因为PI得到了重新生成,IE(也可能是其他浏览器)将其解释为无限循环......用XSLT进行开发的正确方法是通过使用XSLT IDE。我使用XSelerator和oXygen,我从不使用浏览器来运行/测试XSLT转换。其他更丑陋的方法是从命令行调用特定的XSLT处理器。 – 2011-03-22 04:41:32

+0

@Dimitre,+1是绝对正确的,虽然我怀疑你是在这种特殊情况下分裂毛发:) – 2011-03-22 08:39:01