나는 처음부터 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로 설정하면 안됩니다. 그렇지 않으면 이미 부분 들여 쓰기가 포함되어 있으면 실패합니다.
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 ...>
은 XML에서. 조각에는 괜찮지 만 전체 문서에는 바람직하지 않습니다.
더 짧은 확장 메서드 버전
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
간단한 방법은 다음을 사용하는 것입니다.
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();
}
새 줄을 설정할 필요가 없습니다. 들여 쓰기 문자에는 기본적으로 두 개의 공백이 있으므로 설정하지 않는 것이 좋습니다.