How to remove empty XML child tags from an XML

I am looking to remove empty xml tags which are under a particular tag.

For Example, I have this XML:

<?xml version="1.0" encoding="UTF-16"?>
<apiRequest>
   <policyTransaction>
     <addDriver>
       <driverName>xyz</driverName>
       <IsCoInsured/>
       <OnlyInsuredWithThisPolicy/>
     </addDriver>
     <retrieveDrivers/>
     <validateDrivers/>
   </policTransaction>
</apirequest>

I want this to be:

<?xml version="1.0" encoding="UTF-16"?>
    <apiRequest>
       <policyTransaction>
         <addDriver>
           <driverName>xyz</driverName>
         </addDriver>
         <retrieveDrivers/>
         <validateDrivers/>
       </policTransaction>
    </apirequest>

I am using the code below to do this

 var doc= XDocument.Parse(requestString);

 var emptyElements = from descendant in doc.Descendants()
                     where descendant.IsEmpty || string.IsNullOrWhiteSpace(descendant.Value)
                     select descendant;
 emptyElements.Remove();

But the elements after the adddriver also get eliminated.

<?xml version="1.0" encoding="UTF-16"?>
<apiRequest>
   <policyTransaction>
     <addDriver>
       <driverName>xyz</driverName>                                        
     </addDriver>
   </policTransaction>
</apirequest>

Which I don't want to happen. How could I check only for child elements to be removed if they are empty? I want the elements retrieveDrivers and validateDrivers to be there.

The above is obtained by a request, so once this XML is sent I get the response back with the elements for those two tags filled.

Upvotes: 0

Views: 2306

Answers (2)

It is working fine If I use it in this way.

var requestString = XmlSerializer.Serialize(request);

            var requestStringWithoutNullElements = XDocument.Parse(requestString);

            var emptyElements = from descendant in requestStringWithoutNullElements.Descendants()
                                where descendant.IsEmpty && descendant.Name != "retrieveDrivers" && descendant.Name != "validateDrivers"
                                select descendant;
            emptyElements.Remove();

Upvotes: 0

CSharpie
CSharpie

Reputation: 9467

You want to only remove empty elements from a specific element, not the document in general, so instead of

doc.Decendants() 

use

doc.Descendants("addDriver").Elements() // all sub elements of elements called addDriver

This is the most simple solution. This doesnt remove elements that had only empty elements.

Be careful though, if there are namespaces declared, you have to use the correct XName instead of plain string. See this for more info.

Edit


Here is a more generic approach using System; using System.Linq; using System.Xml.Linq;

namespace Sandbox { public class Program {

    public static void Main(string[] args)
    {
        string xml = @"<?xml version='1.0' encoding='UTF-16'?>
<apiRequest>
   <policyTransaction>
     <addDriver>
       <driverName>xyz</driverName>
       <IsCoInsured/>
       <OnlyInsuredWithThisPolicy/>
     </addDriver>
     <retrieveDrivers/>
     <validateDrivers/>
   </policyTransaction>
</apiRequest>";

        XDocument doc = XDocument.Parse(xml);

        doc.Root.RemoveEmptyChildren("addDriver");

        Console.WriteLine(doc);
        Console.ReadKey();
    }
}

public static class XElementExtension
{
    public static void RemoveEmptyChildren(this XElement element, XName name = null, bool recursive = false)
    {
        var children = name != null ? element.Descendants(name) : element.Descendants();
        foreach (var child in children.SelectMany(child => child.Elements()).ToArray())
        {
            if (child.IsEmpty || string.IsNullOrWhiteSpace(child.Value))
                child.Remove();
        }
    }
}

}

Upvotes: 1

Related Questions