Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

XDocument – Convert Open and Close Tags to Self-Closing Tag

NOTE: This is NOT a semantic question. This isn’t asking about what self closing tags mean. This is about doing the OPPOSITE with XDocument than what is mentioned in this example post with C#:
A
Remove self-closing tags (e.g. />) in an XmlDocument

Please read this question thoroughly before linking to a non-applicable duplicate.

I’m writing this because I’ve found so many posts on here and elsewhere that ask about a good way to change self-closing tags in a C# XDocument object to an open and close tag with an empty value.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I want to do the opposite. I want to change this:

<GovtID id="1"></GovtID>

to this:

<GovtID id="1"/>

I want to preserve all attributes and their values that were in the element from before, EXCEPT empty values.

Here’s the latest thing I’ve tried:

private static void CleanUpXElements(XDocument doc)
{
    foreach (XElement childElement in
        from x in doc.DescendantNodes().OfType<XElement>()
        where x.Value == string.Empty
        select x)
    {
        childElement.ReplaceWith(new XElement(childElement.Name.LocalName, childElement.Attributes()));
    };
}

However, when I use this approach, I get a Null Exception when the child element in question gets replaced this way.

Is there a way I can do this without throwing a Null Reference Exception? I see the element change to a self closing tag, but then the Null Exception happens.

>Solution :

I think your problem may be that you are modifying the document’s element tree while iterating through it, causing the iterator to throw an exception when it tries to proceed past the modification.

As an alternative, you could iterate through the elements and, for every element that has no child elements and an empty value, completely remove all child nodes:

public static void CleanUpXElements(this XDocument doc)
{
    foreach (XElement childElement in
             from x in doc.Descendants()
             where !x.IsEmpty && !x.Elements().Any() && string.IsNullOrEmpty(x.Value)
             select x)
    {
        childElement.RemoveNodes();
    };
}

This avoids modifying the element tree while iterating through it and results in <GovtID id="1" />

Demo fiddle here.

Be aware that, as noted by kjhughes, the two empty element forms <GovtID id="1"></GovtID> and <GovtID id="1" /> are semantically identical. As such it should not be necessary to convert one form to the other, and any code that depends on the difference between them is likely broken.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading