Ktos Ktos
Ktos Ktos

Reputation: 3

preventing xsl sheet from generating new elements when <value-of select> is empty

I have to recreate a new xml with different tag names and values from the 'old' xml using xslt 1.0.

My problem is that it generates empty tags even when the value is not there to put in between the tags.

Is there a way of getting rid of those empty tags at the end of the transformation?

I know you could do the for-each loops and do something like that, but the problem with this is that I would need to do multiple transformations which is not desirable:

<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=
  "*[not(node())]
  |
   *[not(node()[2])
   and
     node()/self::text()
   and
     not(normalize-space())
      ]
  "/>
</xsl:stylesheet>

sample xml input:

<root>
<address1>
<line1>line1address1<line1>
<line2>line2address1<line2>
<line3>line3address1<line3>
</address1>
<address2>
<line1/>
<line2/>
<line3/>
</address2>
<address3 />
<address4>
<line1>line1address4<line1>
<line2>line2address4<line2>
<line3/>
</address4>
</root>

sample xml output:

<root>
    <homeAddress>
    <street>line1address1<street>
    <number>line2address1<number>
    <postcode>line3address1<postcode>
    <homeAddress>
    <workAdddress>
    <street>line1address4<street>
    <number>line2address4<number>
    </workAdddress>
  </root>

The sample xml here is not the actual xml I am using so don't worry about it not being well formed.

All the answers seem to be using copy tag and someone was saying that my tags dont match the input xml- this is exactly why I am strugling with this, I cannot do the simple copy and match all empty elements to template that creates nothing. What I need to do is to create new tags with different names and put in them values from input xml differently named tags. Hopefully this will shed a bit of light on this, I am still struggling with this and not sure how to solve this issue.

Upvotes: 0

Views: 56

Answers (3)

Daniel Haley
Daniel Haley

Reputation: 52858

This is similar to the answer by @michael.hor257k, but will also strip out address2

XML Input

<root>
    <address1>
        <line1>line1address1</line1>
        <line2>line2address1</line2>
        <line3>line3address1</line3>
    </address1>
    <address2>
        <line1/>
        <line2/>
        <line3/>
    </address2>
    <address3/>
    <address4>
        <line1>line1address4</line1>
        <line2>line2address4</line2>
        <line3/>
    </address4>
</root>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="*[not(string())]"/>

</xsl:stylesheet>

XML Output

<root>
   <address1>
      <line1>line1address1</line1>
      <line2>line2address1</line2>
      <line3>line3address1</line3>
   </address1>
   <address4>
      <line1>line1address4</line1>
      <line2>line2address4</line2>
   </address4>
</root>

Upvotes: 0

michael.hor257k
michael.hor257k

Reputation: 116993

Do you have an example that wouldn't be handled by:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="*[not(node())]"/>

</xsl:stylesheet>

Upvotes: 0

Gr&#233;gory Vorbe
Gr&#233;gory Vorbe

Reputation: 374

Here is what I have experimented so far. Not complete but this can give you a direction:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output media-type="xml" omit-xml-declaration="yes" indent="yes"/>

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

</xsl:stylesheet>

tested on following XML:

<?xml version="1.0" encoding="UTF-8"?>
<document>
    <element1>TEST1</element1>
    <element2>TEST2</element2>
    <element3/>
    <element4>TEST4</element4>
</document>

Ended up with:

TEST1 TEST2 TEST4

Upvotes: 0

Related Questions