Naomi
Naomi

Reputation: 718

How to check if a node has a single child element which is empty?

I have the following code,

XDocument doc = XDocument.Parse(input);

var nodes = doc.Element(rootNode)
               .Descendants()
               .Where(n => 
                    (n.Value != "0" 
                    && n.Value != ".00" 
                    && n.Value != "false" 
                    && n.Value != "") 
                    || n.HasElements)
               .Select(n => new 
                { 
                    n.Name, 
                    n.Value, 
                    Level = n.Ancestors().Count() - 1, 
                    n.HasElements 
                });

var output = new StringBuilder();    
foreach (var node in nodes)
{
    if (node.HasElements)
    {
        output.AppendLine(new string(' ', node.Level) + node.Name.ToString() + ":");              
    }
else
{
}

My problem is that in case my parent node has only one empty child node, I need to insert one extra blank line. I could not figure out how to check if the only child is empty.

I can get the number of descendants using Descendants = n.Descendants().Count() But I do not see how can I test if that only child is empty or not.

Upvotes: 0

Views: 1139

Answers (2)

Naomi
Naomi

Reputation: 718

I was trying to solve this problem myself and this is what I come up with:

XDocument doc = XDocument.Parse(input);

         var nodes = doc.Element(rootNode).Descendants()
             .Where(n => (n.Value != "0" && n.Value != ".00" && n.Value != "false" && n.Value != "") || n.HasElements)
             .Select(n => new { n.Name, n.Value, Level = n.Ancestors().Count() - 1, 
                n.HasElements, Descendants = n.Descendants().Count(), 
                FirstChildValue = n.HasElements?n.Descendants().FirstOrDefault().Value:"" });

         var output = new StringBuilder();

         foreach (var node in nodes)
         {            
            if (node.HasElements)
            {               
               output.AppendLine(new string(' ', node.Level) + node.Name.ToString() + ":");
               if (0 == node.Level && 1 == node.Descendants && String.IsNullOrWhiteSpace(node.FirstChildValue))
                  output.AppendLine("");
            }

Upvotes: 0

Dmitriy Khaykin
Dmitriy Khaykin

Reputation: 5258

My understanding is that you need all of the parent nodes who only have one child node, and that child node is empty, from what I understand --

Here's a simple test that accomplishes this: It doesn't use your example specifically but accomplishes the task. If you provide what your XML looks like I can try and modify my example to fit your post, if the below is not easily transplanted into your project :)

(Taken from a console app, but the query that actually gets the nodes should work.

static void Main(string[] args)
{
    var xml = @"<root><child><thenode>hello</thenode></child><child><thenode></thenode></child></root>";
    XDocument doc = XDocument.Parse(xml);

    var parentsWithEmptyChild = doc.Element("root")
        .Descendants() // gets all descendants regardless of level
        .Where(d => string.IsNullOrEmpty(d.Value)) // find only ones with an empty value
        .Select(d => d.Parent) // Go one level up to parents of elements that have empty value
        .Where(d => d.Elements().Count() == 1); // Of those that are parents take only the ones that just have one element


    parentsWithEmptyChild.ForEach(Console.WriteLine);

    Console.ReadKey();
}

This returns only the 2nd node, which is the one containing only one empty node, where empty is assumed to be a value of string.Empty.

Upvotes: 2

Related Questions