I need some help with XSLT syntax. Here is my scenario, I have an XML file that needs to be transformed in to a different look and feel of XML file, I have several sections where if particular node set don't contain any value the whole section shouldn't be processed.
Here is an example of XML:
<Dates>
<Date>
<VALUE1></VALUE1>
<VALUE2></VALUE2>
<VALUE3></VALUE3>
<VALUE4></VALUE4>
<VALUE5>3333</VALUE5>
</Date>
<Date>
<VALUE1>AAAA</VALUE1>
<VALUE2></VALUE2>
<VALUE3>JJJJ</VALUE3>
<VALUE4></VALUE4>
<VALUE5>12345</VALUE5>
</Date>
</Dates>
screenshot of xml
Here is my XSLT with the if statement that don't work right
<xsl:for-each select="Level1/Level2/Level3">
<xsl:if test="@VALUE1!=''">
<MyDates>
<value_1>
<xsl:value-of select="VALUE1"/>
</value_1>
<value_2>
<xsl:value-of select="VALUE2"/>
</value_2>
<value_3>
<xsl:value-of select="VALUE3"/>
</value_3>
<value_4>
<xsl:value-of select="VALUE4"/>
</value_4>
</MyDates>
</xsl:if>
</xsl:for-each>
So as you can see I basically want all nodes (VALUE1, VALUE2, VALUE3, etc) to have values or else don't process and move on to the next section
(If you cannot see the XML come thought, I also made a screen shot)
You are trying to match xml elements with names "Level1", "Level2", etc... that don't exist in the document. Then, you are looking for a VALUE1 attribute on the last element.
I think you want something like this:
<xsl:for-each select="Dates">
<MyDates>
<xsl:for-each select="Date">
<xsl:if test="not(*[.=''])">
<MyDate>
<value_1>
<xsl:value-of select="VALUE1"/>
</value_1>
<value_2>
<xsl:value-of select="VALUE2"/>
</value_2>
<value_3>
<xsl:value-of select="VALUE3"/>
</value_3>
<value_4>
<xsl:value-of select="VALUE4"/>
</value_4>
</MyDate>
</xsl:if>
</xsl:for-each>
</MyDates>
</xsl:for-each>
This will add a new MyDate element as long as every value in the corresponding Date element is not empty.
What it does is
*
matches all children. [.='']
means "is empty". Finally, it wraps all that in a not. This means the if only passes if there is not any child that is empty.You may also want to check the W3Schools XSL and XPath tutorials.
You have not defined well what does it mean for "a node to have value".
Most probably, you will consider an element, that has a white space-only text child, not to have value. In this case, below is one solution:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="Date[not(*[not(normalize-space())])]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
This templete for a "Date" element will not be matched if the "Date" contained even one child element, that has no content or only white space.
When this transformation is applied on the following XML document:
<Dates> <Date> <VALUE1></VALUE1> <VALUE2> </VALUE2> <VALUE3></VALUE3> <VALUE4></VALUE4> <VALUE5>3333</VALUE5> </Date> <Date> <VALUE1>AAAA</VALUE1> <VALUE2>1</VALUE2> <VALUE3>JJJJ</VALUE3> <VALUE4>1</VALUE4> <VALUE5>12345</VALUE5> </Date> </Dates>
The correct result is produced:
<Date> <VALUE1>AAAA</VALUE1> <VALUE2>1</VALUE2> <VALUE3>JJJJ</VALUE3> <VALUE4>1</VALUE4> <VALUE5>12345</VALUE5> </Date>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With