In C#, how do I convert a XmlNode to string, with indentation? (Without looping)
Asked Answered
K

2

27

This has got to be such a simple question but I just can't get the answer.

I have an XmlNode and all I want to do is output this node, as a string, with indentations (tabs or spaces) intact to provide better readability.

So far I tried XmlWriter, XmlTextWriter, XmlDocument, XmlReader.

  • I tried the PreserveWhitespace in XmlDocument but I couldn't get the XmlDocument to output my node.
  • I tried the Formatting = Formatting.Indented property in XmlTextWriter but I couldn't figure out how to output the contents to string.

To output the XmlNode as string WITHOUT indentation is easy. I just do XmlNode.OuterXml. How do I get the indentations in there?

I want to do this without looping through the XmlNode and using brute force to add whitespace, because I think there should be a simpler way.

Thanks.

Edit: For future readers, here is the answer:

  var xmlNode = is some object of type XmlNode

  using (var sw = new StringWriter())
  {
      using (var xw = new XmlTextWriter(sw))
      {
        xw.Formatting = Formatting.Indented;
        xw.Indentation = 2; //default is 1. I used 2 to make the indents larger.

        xmlNode.WriteTo(xw);
      }
      return sw.ToString(); //The node, as a string, with indents!
  }

The reason I needed to do this was output the node's xml with syntax highlighting. I used AvalonEdit to highlight the xml, outputted the highlighted text to html, then converted the html to a FlowDocument which could be displayed in a RichTextBox.

Krissy answered 22/6, 2011 at 15:7 Comment(0)
E
34

You were on the right path with the XMLTextWriter, you simply need to use a StringWriter as the base stream. Here are a few good answers on how this is accomplished. Pay particular attention to the second answer, if your encoding needs to be UTF-8.

Edit:

If you need to do this in multiple places, it is trivial to write an extension method to overload a ToString() on XmlNode:

public static class MyExtensions
{
    public static string ToString(this System.Xml.XmlNode node, int indentation)
    {
        using (var sw = new System.IO.StringWriter())
        {
            using (var xw = new System.Xml.XmlTextWriter(sw))
            {
                xw.Formatting = System.Xml.Formatting.Indented;
                xw.Indentation = indentation;
                node.WriteContentTo(xw);
            }
            return sw.ToString();
        }
    }
}
Edmiston answered 22/6, 2011 at 15:16 Comment(4)
thanks for the link! It works. I think I was just searching for the wrong things. I was still stuck on trying to get the node to output even though what I really needed was to get the writer to output to string. Thanks I will update my question with the answer.Krissy
Yes, it's one of the pitfalls of OOP that you sometimes have to wrap objects inside other objects to gain functionality. Thankfully, C# gives us many ways to bring some functional programming into the mix, including extension methods. If you find yourself needing to do this a lot, consider making an extension method like the one in my updated answer.Edmiston
This didn't work for me - unless I called it something other than ToString() (like ToIndentedString()) the standard object.ToString() was called instead.Forging
@Dave, this should work as long as you're passing in an integer parameter to the ToString() method. If you're calling it without parameters, it will default to the original method. This is an overload, not an override.Edmiston
N
5

If you don't care about memory or performance, the simplest thing is:

    XElement.Parse(xmlNode.OuterXml).ToString()
Nishanishi answered 29/3, 2019 at 22:16 Comment(1)
Nice and elegant, especially for scripting, e. g. using PowerShell 7+: [System.Xml.Linq.XElement]::Parse($xmlNode.OuterXml).ToString()Colpin

© 2022 - 2024 — McMap. All rights reserved.