Reputation: 2119
I want to:
<node/>
, <node attr1="" attr2=""/>, <node></node>
<node attr1="123" attr2="" attr3=""/>
and then remove those empty attributes to have <node attr1="123"/>
EXAMPLE
Before
<a>
<b>
<c attr="1"/>
<d/>
</b>
</a>
After
<a>
<b>
<c attr="1"/>
</b>
</a>
I have following 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>
It works pretty good, BUT only if my XML has at least one non-empty node! Example:
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>
After:
<?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>
Works fine, but skipping this non-empty node :
<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>
the output is:
<?xml version="1.0" encoding="UTF-8"?>
Anyone has any idea why it works like this? My code :
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));
Cheers
UPDATE
After using your XSLT the output is:
<?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>
I wonder why there are empty spaces in my output.xml?
Generally speaking, empty node is a node, which
1) istelf has no attributes or all empty AND
2) has no value f.e. <a></a>
, <b/>
AND
3) has no children which carry any data (has no children which meet the requirements 1 and 2) Example explaining empty nodes:
<a>
<b attr="1">
</b>
<c>
<d attr="2">
<e> value </e>
<f></f>
</d>
</a>
a is not empty because it has child b
with attribute attr="1"
(it's enough, but it also has: x, xx, xxx)
b is not empty because it has non-empty attribute
c is not empty because it has d
node with attribute attr="2"
(x) and also has child e
with some value (xxx)
d is not empty becuase it has non-empty attribute (xx)
e is not empty because it has a value (xxx)
f is empty
Upvotes: 0
Views: 1258
Reputation: 116959
You should not make <xsl:apply-templates/>
conditional - otherwise the stylesheet will stop at the first node that does not satisfy the condition, and it will never get to its children.
BTW, if understand your conditions correctly, you could simplify this to:
<xsl:template match="*[string() or @*[string()]]">
<xsl:copy>
<xsl:copy-of select = "@*[string()]"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
Upvotes: 2