XElement
InnerXml
XML parsing
C# programming
.NET

Best way to get InnerXml of an XElement?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

XElement is part of LINQ to XML, which deliberately does not expose the old DOM-style InnerXml property. If you want the XML inside an element, the correct approach is usually to serialize that element's child nodes, not the element itself and not only its text.

Why XElement Has No InnerXml

Developers often come from XmlDocument, where XmlNode.InnerXml is a built-in property. LINQ to XML has a different design. It models XML as strongly typed nodes such as XElement, XText, and XComment, and expects you to work with those nodes directly.

That means there are three different questions you might be asking:

  • "Give me only the text content."
  • "Give me the child nodes as XML."
  • "Give me the entire element including the outer tag."

Those are not the same result, so it is important to choose the right API.

The Usual Answer: Concatenate Nodes()

If you want the equivalent of inner XML, use Nodes() and serialize the child nodes.

csharp
1using System;
2using System.Linq;
3using System.Xml.Linq;
4
5class Program
6{
7    static void Main()
8    {
9        var element = XElement.Parse(
10            "<item><name>Book</name><!--note--><price>10</price></item>"
11        );
12
13        string innerXml = string.Concat(
14            element.Nodes().Select(node => node.ToString(SaveOptions.DisableFormatting))
15        );
16
17        Console.WriteLine(innerXml);
18    }
19}

Output:

text
<name>Book</name><!--note--><price>10</price>

This is usually the best answer because it preserves child elements, comments, and mixed content exactly as nodes.

Do Not Use Value Unless You Only Want Text

Value looks tempting, but it returns only the concatenated text content. It strips markup completely.

csharp
1using System;
2using System.Xml.Linq;
3
4class Program
5{
6    static void Main()
7    {
8        var element = XElement.Parse("<item>Hello <b>world</b></item>");
9
10        Console.WriteLine(element.Value);
11    }
12}

Output:

text
Hello world

That is useful for plain text extraction, but it is not inner XML. If your caller needs the nested tags, Value is the wrong tool.

ToString() Gives Outer XML

At the other extreme, calling ToString() on the element gives you the outer XML, including the element's own start and end tag.

csharp
var element = XElement.Parse("<item><name>Book</name></item>");
Console.WriteLine(element.ToString(SaveOptions.DisableFormatting));

Output:

text
<item><name>Book</name></item>

So the rule is straightforward:

  • 'element.Value gives text only'
  • 'element.ToString(...) gives outer XML'
  • 'string.Concat(element.Nodes()...) gives inner XML'

A Reusable Helper Method

If this comes up often, hide the pattern behind an extension method.

csharp
1using System.Linq;
2using System.Xml.Linq;
3
4public static class XElementExtensions
5{
6    public static string InnerXml(this XElement element)
7    {
8        return string.Concat(
9            element.Nodes().Select(node => node.ToString(SaveOptions.DisableFormatting))
10        );
11    }
12}

Usage:

csharp
var element = XElement.Parse("<root><a>1</a><b>2</b></root>");
string xml = element.InnerXml();
Console.WriteLine(xml);

This keeps calling code readable and makes the intent obvious.

When an XmlWriter Is Useful

If you need more control over how the output is written, you can stream the child nodes through an XmlWriter. That is more verbose, but useful when you want precise writer settings.

csharp
1using System.IO;
2using System.Xml;
3using System.Xml.Linq;
4
5public static string GetInnerXmlWithWriter(XElement element)
6{
7    var settings = new XmlWriterSettings
8    {
9        OmitXmlDeclaration = true,
10        ConformanceLevel = ConformanceLevel.Fragment
11    };
12
13    using var sw = new StringWriter();
14    using (var writer = XmlWriter.Create(sw, settings))
15    {
16        foreach (var node in element.Nodes())
17        {
18            node.WriteTo(writer);
19        }
20    }
21
22    return sw.ToString();
23}

For most cases, string.Concat(element.Nodes()...) is simpler. Reach for the writer approach only when formatting or streaming behavior matters.

Mixed Content Works Correctly

One reason Nodes() is the right abstraction is that XML may contain mixed content, not just child elements. For example:

csharp
var element = XElement.Parse("<p>Hello <b>there</b>, friend.</p>");

The children are:

  • a text node with Hello
  • an element node b
  • another text node with , friend.

Using Nodes() preserves all of that. Using Elements() would lose the text nodes. Using Value would lose the markup.

Common Pitfalls

  • Using Value and expecting markup to be preserved. Value returns text, not XML.
  • Using ToString() and accidentally returning outer XML. That includes the current element's tag as well.
  • Using Elements() instead of Nodes(). Elements() returns child elements only and drops text or comments.
  • Forgetting SaveOptions.DisableFormatting. Default serialization may insert indentation or line breaks that were not intended.
  • Reaching for XmlDocument.InnerXml habits in LINQ to XML code. XElement is a different API with a different model.

Summary

  • 'XElement has no built-in InnerXml property.'
  • The normal LINQ to XML equivalent is string.Concat(element.Nodes().Select(...)).
  • Use Value only when you want text content without markup.
  • Use ToString() only when you want outer XML, including the current tag.
  • Wrap the Nodes() pattern in an extension method if the operation appears often in your codebase.

Course illustration
Course illustration

All Rights Reserved.