を使用してXMLを最初から作成するXmlDocument
と、OuterXml
プロパティはすべて改行でインデントされています。ただし、LoadXml
非常に「圧縮された」XML(改行やインデントなし)を呼び出すと、の出力OuterXml
はそのままになります。そう ...
のインスタンスから美化されたXML出力を取得する最も簡単な方法は何XmlDocument
ですか?
を使用してXMLを最初から作成するXmlDocument
と、OuterXml
プロパティはすべて改行でインデントされています。ただし、LoadXml
非常に「圧縮された」XML(改行やインデントなし)を呼び出すと、の出力OuterXml
はそのままになります。そう ...
のインスタンスから美化されたXML出力を取得する最も簡単な方法は何XmlDocument
ですか?
回答:
他の答えに基づいて、私は調べて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に設定しないでください。それ以外の場合、すでに部分的なインデントが含まれていると失敗します。
適応したようエリカ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();
}
上記のBeautifyメソッドがXmlDocument
すでにXmlProcessingInstruction
子ノードを含むに対して呼び出されている場合、次の例外がスローされます。
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();
}
新しい行を設定する必要はありません。インデント文字にもデフォルトの2つのスペースがあるので、私もそれを設定しないことを選択しました。