tags:

views:

379

answers:

3

I'm looking for a simply way to bring a xml-File with one line without line feeds to a good structured human readable version in C#. Is there any Implementation already in System.XML or a tiny open source framework or a best practice for implementing it?

ex. transform this XML-String:


<Root><Node id="1"><Childnode>Text</Childnode></Node><Node id="2">Text<Kid name="jack" /></Node></Root>

to


<Root>
  <Node id="1">
    <Childnode>
      Text
    </Childnode>
  </Node>
  <Node id="2">
    Text
    <Kid name="jack" />
  </Node>
</Root>
+3  A: 

If you have got Visual Studio:

Create a new XML file and just paste your code. It will re-format it automatically.

alexn
This is what I do!
Josh Stodola
that wasn't what I was asking for. I asked for ''implementing'' it.
Micha
+7  A: 

If you have .NET 3.5:

XDocument document = XDocument.Load(filename);
document.Save(filename);

This will indent automatically. Note that it won't do quite as your question asked, because you're only indenting some of the nodes. That's going to be trickier.

If you're stuck with .NET 2.0, here's Craig's method rejigged and changed to use files instead of strings:

public static void FormatXmlString(string inputFile, string outputFile)
{
    XmlDocument document = new XmlDocument();
    document.Load(inputFile);
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent = true;
    using (XmlWriter writer = XmlWriter.Create(outputFile, settings))
    {
        document.WriteTo(writer);
    }
}

With C# 3 the XmlWriterSettings but could just be:

new XmlWriterSettings { Indent = true }

which could be embedded in the call to XmlWriter.Create, but if you're using .NET 2.0 you probably can't use C# 3.

EDIT: If the input filename part causes a problem, you can use:

XmlDocument document = new XmlDocument();
using (Stream stream = File.OpenRead(inputFile))
{
    document.Load(stream);
}
Jon Skeet
the difference between the 3.5 version and the 2.0 version is that 3.5. is a filename to filename solution and 2.0 a string to string solution. How would be a filename to filename solution in 2.0?
Micha
Create an XmlWriter that writes to a file instead: XmlWriter writer = XmlWriter.Create(filename, settings).
Jon Skeet
Oh, and use document.Load(filename) too. Will edit...
Jon Skeet
Has probably nothing to do with your code. I always get a WebException by document.Load(inputFile) because of missing proxy authentication, but the file is on the local filesystem...
Micha
You could pass in a stream instead. Odd that it tried to load it as a web request even though it presumably didn't start with http:// though :(
Jon Skeet
(I've added an extra bit if you want to change that part of things.)
Jon Skeet
+4  A: 

Here's a handy "FormatXML" class that I wrote for just this purpose:

using System;
using System.Text;
using System.Xml;
using System.IO;

public static class FormatXML
{
    public static string FormatXMLString(string sUnformattedXML)
    {
        XmlDocument xd = new XmlDocument();
        xd.LoadXml(sUnformattedXML);
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);
        XmlTextWriter xtw = null;
        try
        {
            xtw = new XmlTextWriter(sw);
            xtw.Formatting = Formatting.Indented;
            xd.WriteTo(xtw);
        }
        finally
        {
            if(xtw!=null)
                xtw.Close();
        }
        return sb.ToString();
    }
}
CraigTP
xtw pattern looks overcomplicated, using will be better.
arbiter
Not only would a using statement be better, but you can use XmlWriter.Create(sb) to avoid bothering with the StringWriter too.
Jon Skeet
@arbiter, @JonSkeet - You guys are correct in that this code could well be optimized and probably doesn't represent a "perfect" implementation of the mechanism, however, I've used the above code (as-is) in a sample web-service client application that I recently wrote in work and it's worked well for me! By all means, improve it! That's what SO is all about after all! :)
CraigTP
It's not a matter of optimisation, just making the code clearer.
Jon Skeet
@JonSkeet - I know what you're saying, Jon, but I do consider it a kind of optimization since you have removed the need to instantiate a StringWriter object at least. That'll save a small amount of memory overhead if nothing else! :) Plus, it *does* make the code clearer as you say.
CraigTP