Answers:
根据其他答案,我研究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();
}
它的代码比我期望的要多,但它的工作方式只是桃花心木。
settings.Encoding = Encoding.UTF8;
MemoryStream
+ StreamWriter
而不是来解决编码问题StringBuilder
,并使用来获取文本enc.GetString(memstream.GetBuffer(), 0, (int)memstream.Length);
。但是,最终结果仍未格式化。我要从已经格式化的阅读文档开始吗?我只希望新节点也被格式化。
"\r\n"
为Environment.Newline
。
doc.PreserveWhitespace
不应该设置为true。否则,如果它已经包含部分缩进,它将失败。
根据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);
}
using
时,语句将自动关闭作家Dispose()
被调用。
甚至可以轻松访问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);
}
<?xml ...?>
和<!DOCTYPE ...>
。可以使用片段,但不需要完整的文档。
较短的扩展方法版本
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
已经包含XmlProcessingInstruction
子节点的调用上述Beautify方法,则会引发以下异常:
无法编写XML声明。WriteStartDocument方法已经编写了它。
这是我对原始版本的修改后的版本,以消除该异常:
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();
}
}
现在它对我有效,可能您需要扫描该XmlProcessingInstruction
节点的所有子节点,而不仅仅是第一个节点?
2015年4月更新:
由于还有另一种编码错误的情况,因此我搜索了如何在没有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;
}
}
Encoding = Encoding.UTF8
和OmitXmlDeclaration = true
public static string FormatXml(string xml)
{
try
{
var doc = XDocument.Parse(xml);
return doc.ToString();
}
catch (Exception)
{
return xml;
}
}
一种简单的方法是使用:
writer.WriteRaw(space_char);
像此示例代码一样,此代码是我用来使用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();
}
}
这样,您可以按照通常的方式添加制表符或换行符,即\ t或\ n
在实施此处发布的建议时,我在文本编码方面遇到了麻烦。似乎的编码已XmlWriterSettings
被忽略,并且始终被流的编码所覆盖。当使用StringBuilder
,这始终是C#内部使用的文本编码,即UTF-16。
所以这是一个也支持其他编码的版本。
重要说明:如果您的XMLDocument
对象具有其格式,则格式将被完全忽略preserveWhitespace
在加载文档时属性已启用,。这让我难过了一段时间,所以请确保不要启用它。
我的最终代码:
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);
}
}
这将使用给定的文本编码将格式化的xml保存到磁盘。
如果您有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();
}
基于公认答案的更简化方法:
static public string Beautify(this XmlDocument doc) {
StringBuilder sb = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true
};
using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
doc.Save(writer);
}
return sb.ToString();
}
无需设置新行。缩进字符也具有默认的两个空格,因此我也不想设置它。