Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT To remove empty nodes and nodes with -1

Tags:

xml

xslt

I'm not an XSLT wizard.

I have the current XSLT i'm using to remove empty nodes:

 string strippingStylesheet = "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" +
                "<xsl:template match=\"@*|node()\">" +
                "<xsl:if test=\". != ''\">" +
                "<xsl:copy>" + 
                "<xsl:apply-templates select=\"@*|node()\"/>" +
                "</xsl:copy>" + 
                "</xsl:if></xsl:template></xsl:stylesheet>";

I need to find a way to also remove nodes with -1 in them. A previous developer thought it would be a good idea to make every int in the system be defaulted to -1, and yes that means all DB fields have -1 in them instead of null.

So as much as I want to beat the dead horse (with a stick, bat, bazooka), I need to get back to work and get this done.

Any help would be great.

like image 223
Ryan Ternier Avatar asked Dec 10 '10 00:12

Ryan Ternier


2 Answers

I have the current XSLT i'm using to remove empty nodes:

. . . . . . . . .

I need to find a way to also remove nodes with -1 in them

I guess that it is required to remove all "empty nodes".

The processing depends on the definition of "empty node". One reasonable definition in your case is: Any element that doesn't have attributes and children or doesn't have attributes and has only one child that is a text node with value -1.

For this definition here is a simple solution.

This transformation:

<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(@*) and not(*) and (not(text()) or .=-1)]"/>
</xsl:stylesheet>

when applied on this sample XML document:

<t>
 <a>-1</a>
 <a>2</a>
 <b><c/></b>
 <d>-1</d>
 <d>15</d>
 <e x="1"/>
 <f>foo</f>
</t>

produces the wanted, correct result:

<t>
   <a>2</a>
   <b/>
   <d>15</d>
   <e x="1"/>
   <f>foo</f>
</t>
like image 62
Dimitre Novatchev Avatar answered Oct 18 '22 14:10

Dimitre Novatchev


In simple case this should work:

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

<xsl:template match="*[. = '' or . = '-1']"/>

With this simple input:

<root>
    <node></node>
    <node>-1</node>
    <node>2</node>
    <node>8</node>
    <node>abc</node>
    <node>-1</node>
    <node></node>
    <node>99</node>
</root>

Result will be:

<root>
    <node>2</node>
    <node>8</node>
    <node>abc</node>
    <node>99</node>
</root>
like image 5
Flack Avatar answered Oct 18 '22 13:10

Flack