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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/203528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:52:52  来源:igfitidea点击:

What is the simplest way to get indented XML with line breaks from XmlDocument?

c#.netxmldocumentouterxml

提问by Neil C. Obremski

When I build XML up from scratch with XmlDocument, the OuterXmlproperty already has everything nicely indented with line breaks. However, if I call LoadXmlon some very "compressed" XML (no line breaks or indention) then the output of OuterXmlstays that way. So ...

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

What is the simplest way to get beautified XML output from an instance of XmlDocument?

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

采纳答案by Neil C. Obremski

Based on the other answers, I looked into XmlTextWriterand came up with the following helper method:

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

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();
}

It's a bit more code than I hoped for, but it works just peachy.

它的代码比我希望的要多一些,但它的工作原理很好。

回答by DocMax

As adapted from Erika Ehrli'sblog, this should do it:

改编自Erika Ehrli 的博客,应该这样做:

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);
}

回答by benPearce

XmlTextWriter xw = new XmlTextWriter(writer);
xw.Formatting = Formatting.Indented;

回答by Uwe Keim

If the above Beautify method is being called for an XmlDocumentthat already contains an XmlProcessingInstructionchild node the following exception is thrown:

如果为XmlDocument已经包含XmlProcessingInstruction子节点的调用上述 Beautify 方法,则会引发以下异常:

Cannot write XML declaration. WriteStartDocument method has already written it.

无法编写 XML 声明。WriteStartDocument 方法已经写好了。

This is my modified version of the original one to get rid of the exception:

这是我为摆脱异常而修改的原始版本:

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();
    }
}

It works for me now, probably you would need to scan all child nodes for the XmlProcessingInstructionnode, not just the first one?

它现在对我有用,可能您需要扫描节点的所有子XmlProcessingInstruction节点,而不仅仅是第一个?



Update April 2015:

2015 年 4 月更新:

Since I had another case where the encoding was wrong, I searched for how to enforce UTF-8 without BOM. I found this blog postand created a function based on it:

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

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;
    }
}

回答by Jonathan Mitchem

A shorter extension method version

较短的扩展方法版本

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();
}

回答by Munim Dibosh

A simple way is to use:

一个简单的方法是使用:

writer.WriteRaw(space_char);

Like this sample code, this code is what I used to create a tree view like structure using XMLWriter :

像这个示例代码一样,这个代码是我用来使用 XMLWriter 创建树状视图结构的代码:

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();

            }

        }

This way you can add tab or line breaks in the way you are normally used to, i.e. \t or \n

这样你就可以按照你通常习惯的方式添加制表符或换行符,即 \t 或 \n

回答by JFK

Or even easier if you have access to Linq

如果您可以访问 Linq 甚至更容易

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);
}

回答by Nyerguds

When implementing the suggestions posted here, I had trouble with the text encoding. It seems the encoding of the XmlWriterSettingsis ignored, and always overridden by the encoding of the stream. When using a StringBuilder, this is always the text encoding used internally in C#, namely UTF-16.

在实施此处发布的建议时,我在文本编码方面遇到了问题。似乎XmlWriterSettings忽略了 的编码,并且总是被流的编码覆盖。使用 a 时StringBuilder,这始终是 C# 内部使用的文本编码,即 UTF-16。

So here's a version which supports other encodings as well.

所以这里有一个支持其他编码的版本。

IMPORTANT NOTE: The formatting is completely ignored if your XMLDocumentobject has its preserveWhitespaceproperty enabled when loading the document. This had me stumped for a while, so make sure not to enable that.

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

My final code:

我的最终代码:

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);
    }
}

This will save the formatted xml to disk, with the given text encoding.

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

回答by theJerm

If you have a string of XML, rather than a doc ready for use, you can do it this way:

如果您有一个 XML 字符串,而不是一个可供使用的文档,您可以这样做:

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();
}

回答by rewrew

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