Формат XML-строки для печати дружественной XML-строки
У меня есть строка XML как таковая:
<?xml version='1.0'?><response><error code='1'> Success</error></response>
Там нет линий между одним элементом и другим, и поэтому очень трудно читать. Я хочу функцию, которая форматирует вышеуказанную строку:
<?xml version='1.0'?>
<response>
<error code='1'> Success</error>
</response>
Не прибегая к ручному написанию функции форматирования самостоятельно, есть ли какая-либо библиотека.Net или фрагмент кода, которые я могу использовать на месте?
12 ответов
Использовать XmlTextWriter...
public static string PrintXML(string xml)
{
string result = "";
MemoryStream mStream = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter(mStream, Encoding.Unicode);
XmlDocument document = new XmlDocument();
try
{
// Load the XmlDocument with the XML.
document.LoadXml(xml);
writer.Formatting = Formatting.Indented;
// Write the XML into a formatting XmlTextWriter
document.WriteContentTo(writer);
writer.Flush();
mStream.Flush();
// Have to rewind the MemoryStream in order to read
// its contents.
mStream.Position = 0;
// Read MemoryStream contents into a StreamReader.
StreamReader sReader = new StreamReader(mStream);
// Extract the text from the StreamReader.
string formattedXml = sReader.ReadToEnd();
result = formattedXml;
}
catch (XmlException)
{
// Handle the exception
}
mStream.Close();
writer.Close();
return result;
}
Вам придется как-то анализировать контент... Я считаю, что с помощью LINQ это самый простой способ сделать это. Опять же, все зависит от вашего точного сценария. Вот рабочий пример использования LINQ для форматирования входной строки XML.
string FormatXml(string xml)
{
try
{
XDocument doc = XDocument.Parse(xml);
return doc.ToString();
}
catch (Exception)
{
// Handle and throw if fatal exception here; don't just ignore them
return xml;
}
}
[использование высказываний опущено для краткости]
Этот, от Кристоферджонсона, намного лучше:
- Он также не требует заголовка документа XML.
- Имеет более четкие исключения
- Добавляет дополнительные параметры поведения: OmitXmlDeclaration = true, NewLineOnAttributes = true
Меньше строк кода
static string PrettyXml(string xml) { var stringBuilder = new StringBuilder(); var element = XElement.Parse(xml); var settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; settings.Indent = true; settings.NewLineOnAttributes = true; using (var xmlWriter = XmlWriter.Create(stringBuilder, settings)) { element.Save(xmlWriter); } return stringBuilder.ToString(); }
Простое решение, которое работает для меня:
XmlDocument xmlDoc = new XmlDocument();
StringWriter sw = new StringWriter();
xmlDoc.LoadXml(rawStringXML);
xmlDoc.Save(sw);
String formattedXml = sw.ToString();
Проверьте следующую ссылку: Как красиво печатать XML (К сожалению, теперь ссылка возвращает 404:()
Метод в ссылке принимает строку XML в качестве аргумента и возвращает правильно сформированную (с отступом) строку XML.
Я просто скопировал пример кода по ссылке, чтобы сделать этот ответ более полным и удобным.
public static String PrettyPrint(String XML)
{
String Result = "";
MemoryStream MS = new MemoryStream();
XmlTextWriter W = new XmlTextWriter(MS, Encoding.Unicode);
XmlDocument D = new XmlDocument();
try
{
// Load the XmlDocument with the XML.
D.LoadXml(XML);
W.Formatting = Formatting.Indented;
// Write the XML into a formatting XmlTextWriter
D.WriteContentTo(W);
W.Flush();
MS.Flush();
// Have to rewind the MemoryStream in order to read
// its contents.
MS.Position = 0;
// Read MemoryStream contents into a StreamReader.
StreamReader SR = new StreamReader(MS);
// Extract the text from the StreamReader.
String FormattedXML = SR.ReadToEnd();
Result = FormattedXML;
}
catch (XmlException)
{
}
MS.Close();
W.Close();
return Result;
}
Я старался:
internal static void IndentedNewWSDLString(string filePath)
{
var xml = File.ReadAllText(filePath);
XDocument doc = XDocument.Parse(xml);
File.WriteAllText(filePath, doc.ToString());
}
он работает нормально, как и ожидалось.
.NET 2.0 игнорирует разрешение имен, а также с надлежащим удалением ресурсов, отступом, сохранением пробелов и пользовательской кодировкой:
public static string Beautify(System.Xml.XmlDocument doc)
{
string strRetValue = null;
System.Text.Encoding enc = System.Text.Encoding.UTF8;
// enc = new System.Text.UTF8Encoding(false);
System.Xml.XmlWriterSettings xmlWriterSettings = new System.Xml.XmlWriterSettings();
xmlWriterSettings.Encoding = enc;
xmlWriterSettings.Indent = true;
xmlWriterSettings.IndentChars = " ";
xmlWriterSettings.NewLineChars = "\r\n";
xmlWriterSettings.NewLineHandling = System.Xml.NewLineHandling.Replace;
//xmlWriterSettings.OmitXmlDeclaration = true;
xmlWriterSettings.ConformanceLevel = System.Xml.ConformanceLevel.Document;
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(ms, xmlWriterSettings))
{
doc.Save(writer);
writer.Flush();
ms.Flush();
writer.Close();
} // End Using writer
ms.Position = 0;
using (System.IO.StreamReader sr = new System.IO.StreamReader(ms, enc))
{
// Extract the text from the StreamReader.
strRetValue = sr.ReadToEnd();
sr.Close();
} // End Using sr
ms.Close();
} // End Using ms
/*
System.Text.StringBuilder sb = new System.Text.StringBuilder(); // Always yields UTF-16, no matter the set encoding
using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(sb, settings))
{
doc.Save(writer);
writer.Close();
} // End Using writer
strRetValue = sb.ToString();
sb.Length = 0;
sb = null;
*/
xmlWriterSettings = null;
return strRetValue;
} // End Function Beautify
Использование:
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
xmlDoc.XmlResolver = null;
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("C:\Test.svg");
string SVG = Beautify(xmlDoc);
Можно распечатать строку XML с помощью потокового преобразования с помощьюXmlWriter.WriteNode(XmlReader, true)
. Этот способ
копирует все от читателя к писателю и перемещает читателя к началу следующего брата.
Определите следующие методы расширения:
public static class XmlExtensions
{
public static string FormatXml(this string xml, bool indent = true, bool newLineOnAttributes = false, string indentChars = " ", ConformanceLevel conformanceLevel = ConformanceLevel.Document) =>
xml.FormatXml( new XmlWriterSettings { Indent = indent, NewLineOnAttributes = newLineOnAttributes, IndentChars = indentChars, ConformanceLevel = conformanceLevel });
public static string FormatXml(this string xml, XmlWriterSettings settings)
{
using (var textReader = new StringReader(xml))
using (var xmlReader = XmlReader.Create(textReader, new XmlReaderSettings { ConformanceLevel = settings.ConformanceLevel } ))
using (var textWriter = new StringWriter())
{
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
xmlWriter.WriteNode(xmlReader, true);
return textWriter.ToString();
}
}
}
И теперь вы сможете:
var inXml = @"<?xml version='1.0'?><response><error code='1'> Success</error></response>";
var newXml = inXml.FormatXml(indentChars : "", newLineOnAttributes : false); // Or true, if you prefer
Console.WriteLine(newXml);
Какие отпечатки
<?xml version='1.0'?>
<response>
<error code="1"> Success</error>
</response>
Заметки:
Другие ответы загружают XML в некоторую объектную модель документа, такую как
XmlDocument
или жеXDocument
/XElement
, затем повторно сериализуйте DOM с включенным отступом.Это потоковое решение полностью избегает дополнительных накладных расходов памяти DOM.
В своем вопросе вы не добавляете отступы для вложенных
<error code='1'> Success</error>
узел, поэтому я установилindentChars : ""
. Обычно используется отступ в два пробела на каждый уровень вложенности.Разделители атрибутов будут безоговорочно преобразованы в двойные кавычки, если в настоящее время заключены в одинарные кавычки. (Я считаю, что это верно и для других ответов.)
Проходящий
conformanceLevel : ConformanceLevel.Fragment
позволяет форматировать строки, содержащие последовательности фрагментов XML.Кроме как
ConformanceLevel.Fragment
, входная строка XML должна быть правильно сформированной. Если это не так,XmlReader
вызовет исключение.
Демо скрипка здесь.
Настраиваемый вывод Pretty XML с объявлением UTF-8 XML
Следующее определение класса дает простой метод для преобразования входной строки XML в форматированный выходной XML с объявлением xml как UTF-8. Он поддерживает все параметры конфигурации, которые предлагает класс XmlWriterSettings.
using System;
using System.Text;
using System.Xml;
using System.IO;
namespace CJBS.Demo
{
/// <summary>
/// Supports formatting for XML in a format that is easily human-readable.
/// </summary>
public static class PrettyXmlFormatter
{
/// <summary>
/// Generates formatted UTF-8 XML for the content in the <paramref name="doc"/>
/// </summary>
/// <param name="doc">XmlDocument for which content will be returned as a formatted string</param>
/// <returns>Formatted (indented) XML string</returns>
public static string GetPrettyXml(XmlDocument doc)
{
// Configure how XML is to be formatted
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true
, IndentChars = " "
, NewLineChars = System.Environment.NewLine
, NewLineHandling = NewLineHandling.Replace
//,NewLineOnAttributes = true
//,OmitXmlDeclaration = false
};
// Use wrapper class that supports UTF-8 encoding
StringWriterWithEncoding sw = new StringWriterWithEncoding(Encoding.UTF8);
// Output formatted XML to StringWriter
using (XmlWriter writer = XmlWriter.Create(sw, settings))
{
doc.Save(writer);
}
// Get formatted text from writer
return sw.ToString();
}
/// <summary>
/// Wrapper class around <see cref="StringWriter"/> that supports encoding.
/// Attribution: http://stackru.com/a/427737/3063884
/// </summary>
private sealed class StringWriterWithEncoding : StringWriter
{
private readonly Encoding encoding;
/// <summary>
/// Creates a new <see cref="PrettyXmlFormatter"/> with the specified encoding
/// </summary>
/// <param name="encoding"></param>
public StringWriterWithEncoding(Encoding encoding)
{
this.encoding = encoding;
}
/// <summary>
/// Encoding to use when dealing with text
/// </summary>
public override Encoding Encoding
{
get { return encoding; }
}
}
}
}
Возможности для дальнейшего улучшения:-
- Дополнительный метод
GetPrettyXml(XmlDocument doc, XmlWriterSettings settings)
может быть создан, что позволяет вызывающему абоненту настроить вывод. - Дополнительный метод
GetPrettyXml(String rawXml)
может быть добавлено, что поддерживает синтаксический анализ необработанного текста, вместо того, чтобы клиент использовал XmlDocument. В моем случае мне нужно было манипулировать XML с помощью XmlDocument, поэтому я не добавил это.
Использование:
String myFormattedXml = null;
XmlDocument doc = new XmlDocument();
try
{
doc.LoadXml(myRawXmlString);
myFormattedXml = PrettyXmlFormatter.GetPrettyXml(doc);
}
catch(XmlException ex)
{
// Failed to parse XML -- use original XML as formatted XML
myFormattedXml = myRawXmlString;
}
Проверьте следующую ссылку: Отформатируйте файл XML, чтобы он хорошо смотрелся на C#
// Format the XML text.
StringWriter string_writer = new StringWriter();
XmlTextWriter xml_text_writer = new XmlTextWriter(string_writer);
xml_text_writer.Formatting = Formatting.Indented;
xml_document.WriteTo(xml_text_writer);
// Display the result.
txtResult.Text = string_writer.ToString();
Если вы загрузите XMLDoc, я почти уверен, что функция.ToString() имеет для этого перегрузку.
Но это для отладки? Причина, по которой он отправляется таким образом, заключается в том, что он занимает меньше места (то есть удаляет ненужные пробелы из XML).
Привет, почему бы тебе просто не попробовать это:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = false;
....
....
xmlDoc.Save(fileName);
PreserveWhitespace = ложь; этот вариант также можно использовать для украшения xml.