从XmlDocument获得带换行符的缩进XML的最简单方法是什么?

问题描述 投票:103回答:11

[当我使用XmlDocument从头开始构建XML时,OuterXml属性已经很好地包含了所有带有换行符的缩进。但是,如果我在一些非常“压缩”的XML(没有换行或缩进)上调用LoadXml,则OuterXml的输出将保持这种状态。所以...

XmlDocument实例获取美化XML输出的最简单方法是什么?

c# .net xmldocument outerxml
11个回答
203
投票

基于其他答案,我研究了XmlTextWriter,并提出了以下帮助方法:

XmlTextWriter

比我期望的要多的代码,但它的工作原理只是桃花心的。


1
投票

如果您有一个XML字符串,而不是准备使用的文档,则可以这样操作:

public static void SaveFormattedXml(XmlDocument doc, String outputPath, Encoding encoding)
{
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent = true;
    settings.IndentChars = "\t";
    settings.NewLineChars = "\r\n";
    settings.NewLineHandling = NewLineHandling.Replace;

    using (MemoryStream memstream = new MemoryStream())
    using (StreamWriter sr = new StreamWriter(memstream, encoding))
    using (XmlWriter writer = XmlWriter.Create(sr, settings))
    using (FileStream fileWriter = new FileStream(outputPath, FileMode.Create))
    {
        if (doc.ChildNodes.Count > 0 && doc.ChildNodes[0] is XmlProcessingInstruction)
            doc.RemoveChild(doc.ChildNodes[0]);
        // save xml to XmlWriter made on encoding-specified text writer
        doc.Save(writer);
        // Flush the streams (not sure if this is really needed for pure mem operations)
        writer.Flush();
        // Write the underlying stream of the XmlWriter to file.
        fileWriter.Write(memstream.GetBuffer(), 0, (Int32)memstream.Length);
    }
}

1
投票

基于公认答案的更简化方法:

var xmlString = "<xml>...</xml>"; // Your original XML string that needs indenting.
xmlString = this.PrettifyXml(xmlString);

private string PrettifyXml(string xmlString)
{
    var prettyXmlString = new StringBuilder();

    var xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(xmlString);

    var xmlSettings = new XmlWriterSettings()
    {
        Indent = true,
        IndentChars = " ",
        NewLineChars = "\r\n",
        NewLineHandling = NewLineHandling.Replace
    };

    using (XmlWriter writer = XmlWriter.Create(prettyXmlString, xmlSettings))
    {
        xmlDoc.Save(writer);
    }

    return prettyXmlString.ToString();
}

没有必要设置新行。缩进字符也具有默认的两个空格,因此我也不想设置它。


46
投票

根据static public string Beautify(this XmlDocument doc) { StringBuilder sb = new StringBuilder(); XmlWriterSettings settings = new XmlWriterSettings { Indent = true, IndentChars = " ", NewLineChars = "\r\n", NewLineHandling = NewLineHandling.Replace }; using (XmlWriter writer = XmlWriter.Create(sb, settings)) { doc.Save(writer); } return sb.ToString(); } 博客改编,应该这样做:

Erika Ehrli's

39
投票

或者如果您可以使用Linq,甚至会更容易

XmlDocument doc = new XmlDocument();
doc.LoadXml("<item><name>wrench</name></item>");
// Save the document to a file and auto-indent the output.
using (XmlTextWriter writer = new XmlTextWriter("data.xml", null)) {
    writer.Formatting = Formatting.Indented;
    doc.Save(writer);
}

16
投票

更短的扩展方法版本

try
{
    RequestPane.Text = System.Xml.Linq.XElement.Parse(RequestPane.Text).ToString();
}
catch (System.Xml.XmlException xex)
{
            displayException("Problem with formating text in Request Pane: ", xex);
}

11
投票

如果正在为已经包含public static string ToIndentedString( this XmlDocument doc ) { var stringWriter = new StringWriter(new StringBuilder()); var xmlTextWriter = new XmlTextWriter(stringWriter) {Formatting = Formatting.Indented}; doc.Save( xmlTextWriter ); return stringWriter.ToString(); } 子节点的XmlDocument调用上述Beautify方法,则会引发以下异常:

无法编写XML声明。WriteStartDocument方法已经写下来。

这是我对原始版本的修改版本,以摆脱异常:

XmlProcessingInstruction

现在对我有用,可能您需要扫描所有子节点的private static string beautify( XmlDocument doc) { var sb = new StringBuilder(); var settings = new XmlWriterSettings { Indent = true, IndentChars = @" ", NewLineChars = Environment.NewLine, NewLineHandling = NewLineHandling.Replace, }; using (var writer = XmlWriter.Create(sb, settings)) { if (doc.ChildNodes[0] is XmlProcessingInstruction) { doc.RemoveChild(doc.ChildNodes[0]); } doc.Save(writer); return sb.ToString(); } } 节点,而不仅仅是第一个?


2015年4月更新:

由于存在另一种编码错误的情况,因此我搜索了如何在没有BOM的情况下强制执行UTF-8。我找到了XmlProcessingInstruction并基于它创建了一个函数:

this blog post

7
投票
private static string beautify(string xml)
{
    var doc = new XmlDocument();
    doc.LoadXml(xml);

    var settings = new XmlWriterSettings
    {
        Indent = true,
        IndentChars = "\t",
        NewLineChars = Environment.NewLine,
        NewLineHandling = NewLineHandling.Replace,
        Encoding = new UTF8Encoding(false)
    };

    using (var ms = new MemoryStream())
    using (var writer = XmlWriter.Create(ms, settings))
    {
        doc.Save(writer);
        var xmlString = Encoding.UTF8.GetString(ms.ToArray());
        return xmlString;
    }
}

5
投票
XmlTextWriter xw = new XmlTextWriter(writer);
xw.Formatting = Formatting.Indented;

2
投票

一种简单的方法是使用:

    public static string FormatXml(string xml)
    {
        try
        {
            var doc = XDocument.Parse(xml);
            return doc.ToString();
        }
        catch (Exception)
        {
            return xml;
        }
    }

像此示例代码一样,该代码是我用来使用XMLWriter创建类似于结构的树视图的代码:

writer.WriteRaw(space_char);

通过这种方式,您可以按照通常的方式添加制表符或换行符,例如\ t或\ n


1
投票

[执行此处发布的建议时,我在文本编码方面遇到了麻烦。似乎private void generateXML(string filename) { using (XmlWriter writer = XmlWriter.Create(filename)) { writer.WriteStartDocument(); //new line writer.WriteRaw("\n"); writer.WriteStartElement("treeitems"); //new line writer.WriteRaw("\n"); foreach (RootItem root in roots) { //indent writer.WriteRaw("\t"); writer.WriteStartElement("treeitem"); writer.WriteAttributeString("name", root.name); writer.WriteAttributeString("uri", root.uri); writer.WriteAttributeString("fontsize", root.fontsize); writer.WriteAttributeString("icon", root.icon); if (root.children.Count != 0) { foreach (ChildItem child in children) { //indent writer.WriteRaw("\t"); writer.WriteStartElement("treeitem"); writer.WriteAttributeString("name", child.name); writer.WriteAttributeString("uri", child.uri); writer.WriteAttributeString("fontsize", child.fontsize); writer.WriteAttributeString("icon", child.icon); writer.WriteEndElement(); //new line writer.WriteRaw("\n"); } } writer.WriteEndElement(); //new line writer.WriteRaw("\n"); } writer.WriteEndElement(); writer.WriteEndDocument(); } } 的编码被忽略,并且始终被流的编码覆盖。使用XmlWriterSettings时,始终是C#内部使用的文本编码,即UTF-16。

所以这也是一个支持其他编码的版本。

重要说明:如果在加载文档时StringBuilder对象启用了XMLDocument属性,则格式将被完全忽略。这让我难过了一段时间,所以请确保不要启用它。

我的最终代码:

preserveWhitespace

这将使用给定的文本编码将格式化的xml保存到磁盘。

© www.soinside.com 2019 - 2024. All rights reserved.