使用XSLT删除空/无属性的空节点

时间:2015-05-14 20:11:40

标签: java xml xslt xslt-2.0

我想:

  • 删除所有空节点,没有或所有空属性f.e. <node/><node attr1="" attr2=""/>, <node></node>
  • 保留那些至少有一个非空属性f.e的节点。 <node attr1="123" attr2="" attr3=""/>然后删除这些空属性以使其具有<node attr1="123"/>
  • UPDATED 保留那些至少有一个非空子节点或至少有一个节点具有某些属性的空节点

示例

<a>
  <b>
    <c attr="1"/>
    <d/>
  </b>
</a>

<a>
  <b>
    <c attr="1"/>
  </b>
</a>

我有以下XSLT:

<xsl:template match="@*|node()">
        <xsl:if test="normalize-space(.) != '' or ./@* != ''">
            <xsl:copy>
                <xsl:copy-of select = "@*[.!='']"/>
                <xsl:apply-templates/>
            </xsl:copy>
        </xsl:if>
</xsl:template>

它工作得很好,但前提是我的XML至少有一个非空节点! 例如:

XML:

<ns1:form xmlns:ns1="http://aaa.com">
  <ns1:test>
    <a></a>
    <b attr1=""/>
    <c attr="123"/>
    <d attr="">
      <e attr="12">NOT EMPTY NODE</e>
    </d>
  </ns1:test>
</ns1:form>

后:

<?xml version="1.0" encoding="UTF-8"?><ns1:form xmlns:ns1="http://aaa.com">
  <ns1:test>
    <c attr="123"/>
    <d>
      <e attr="12">NOT EMPTY NODE</e>
    </d>
  </ns1:test>
</ns1:form>

工作正常,但跳过这个非空节点:

<ns1:form xmlns:ns1="http://aaa.com">
  <ns1:test>
    <a></a>
    <b attr1=""/>
    <c attr="123"/>
    <d attr="">
      <e attr="12"></e>
    </d>
  </ns1:test>
</ns1:form>

输出是:

<?xml version="1.0" encoding="UTF-8"?>

任何人都知道它为什么会这样?我的代码:

    TransformerFactory factory = TransformerFactory.newInstance();
    InputStream in = new FileInputStream(new File("transform.xslt"));

    Source xslt = new StreamSource(in);
    Transformer transformer = factory.newTransformer(xslt);
    Source text = new StreamSource(new File("input.xml"));

    StringReader reader = new StringReader(xml);
    Source text = new StreamSource(reader);
    transformer.transform(text, new StreamResult(writer));

干杯

更新

使用XSLT后输出为:

<?xml version="1.0" encoding="UTF-8"?><ns1:form xmlns:ns1="http://aaa.com">
<ns1:test>


<c attr="123"/>
<d>
    <e attr="12">e</e>
</d>
</ns1:test>
</ns1:form>

我想知道为什么output.xml中有空格?

一般来说,空节点是一个节点,

1)istelf没有属性或全是空的

2)没有价值f.e. <a></a><b/>

3)没有携带任何数据的孩子(没有符合要求1和2的孩子) 解释空节点的示例:

<a>
  <b attr="1">
  </b>
  <c>
  <d attr="2">
    <e> value </e>
    <f></f>
  </d>
</a>

a不是空的,因为它有子b,其属性为attr="1"(它足够了,但它也有:x,xx,xxx)

b不为空,因为它具有非空属性

c不为空,因为它有d个属性为attr="2"(x)的节点,并且还有子e具有某个值(xxx)

d不为空,因为它具有非空属性(xx)

e不为空,因为它有一个值(xxx)

f为空

1 个答案:

答案 0 :(得分:2)

你不应该使<xsl:apply-templates/>成为条件 - 否则样式表将停在第一个不满足条件的节点上,它永远不会到达它的子节点。

顺便说一下,如果你能正确理解你的情况,可以将其简化为:

<xsl:template match="*[string() or @*[string()]]">
    <xsl:copy>
        <xsl:copy-of select = "@*[string()]"/>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>