XML-отступы при введении XML-строки в XmlWriter
У меня есть XmlTextWriter, пишущий в файл, и XmlWriter, использующий этот текстовый писатель. Этот текстовый редактор настроен на вывод XML с отступом от табуляции:
XmlTextWriter xtw = new XmlTextWriter("foo.xml", Encoding.UTF8);
xtw.Formatting = Formatting.Indented;
xtw.IndentChar = 't';
xtw.Indentation = 1;
XmlWriter xw = XmlWriter.Create(xtw);
Изменено по ссылке MSDN Джеффа:
XmlWriterSettings set = new XmlWriterSettings();
set.Indent = true;
set.IndentChars = "t";
set.Encoding = Encoding.UTF8;
xw = XmlWriter.Create(f, set);
Это не меняет конечного результата.
Теперь я произвольная глубина в моем XmlWriter, и я получаю строку XML из другого места (которую я не могу контролировать), которая является однострочным, без отступов XML. Если я позвоню xw.WriteRaw () затем эта строка вводится дословно и делает не следовать моему отступу я хочу.
...
string xml = ExternalMethod();
xw.WriteRaw(xml);
...
По существу, я хочу WriteRaw, который будет анализировать XML-строку и проходить через все WriteStartElement и т. д. так что он будет переформатирован в соответствии с настройками XmlTextWriter.
Мое предпочтение-это способ сделать это с настройкой, которая у меня уже есть, и сделать это без необходимости перезагружать окончательный XML, чтобы просто переформатировать его. Я также предпочел бы не разбирать XML-строку с подобными XmlReader, а затем имитировать то, что он находит в моем XmlWriter (очень очень ручной процесс).
В конце концов, я бы предпочел простое решение, чем то, которое следует моим предпочтениям. (Лучшее решение, естественно, было бы простым и соответствует моим предпочтениям.)
6 ответов:
Как насчет использования XmlReader для чтения xml как узлов xml?
string xml = ExternalMethod(); XmlReader reader = XmlReader.Create(new StringReader(xml)); xw.WriteNode(reader, true);
Вы не должны использовать
XmlTextWriter, как указано в MSDN, где он гласит:В .NET Framework версии 2.0 освобождение, рекомендуемая практика для создания экземпляров XmlWriter с помощью XmlWriter.Создайте метод и Класс XmlWriterSettings. Это позволяет вы, чтобы в полной мере воспользоваться всеми преимуществами новые возможности, представленные в этом освобождать. Для получения дополнительной информации см. Создание XML-писателей.
Вместо этого следует использовать XmlWriter.Создать , чтобы получить ваш писатель. Затем вы можете использовать
XmlWriterSettingsкласс для указания таких вещей, как отступ.XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "\t";Обновление
Я думаю, что вы можете просто использовать WriteNode. Вы берете свою xml-строку и загружаете ее в XDocument или XmlReader, а затем используете узел из этого, чтобы записать ее в свой XmlWriter.
Это лучшее, что у меня есть до сих пор. Очень ручной процесс, который поддерживает только то, что написано. Моя строка XML - это не что иное, как теги, атрибуты и текстовые данные. Если он поддерживает пространства имен, CDATA и т. д. тогда это должно было бы расти соответственно.
Очень ручной, очень грязный и очень вероятно склонный к ошибкам, но он выполняет мои предпочтения.
private static void PipeXMLIntoWriter(XmlWriter xw, string xml) { byte[] dat = new System.Text.UTF8Encoding().GetBytes(xml); MemoryStream m = new MemoryStream(); m.Write(dat, 0, dat.Length); m.Seek(0, SeekOrigin.Begin); XmlReader r = XmlReader.Create(m); while (r.Read()) { switch (r.NodeType) { case XmlNodeType.Element: xw.WriteStartElement(r.Name); if (r.HasAttributes) { for (int i = 0; i < r.AttributeCount; i++) { r.MoveToAttribute(i); xw.WriteAttributeString(r.Name, r.Value); } } if (r.IsEmptyElement) { xw.WriteEndElement(); } break; case XmlNodeType.EndElement: xw.WriteEndElement(); break; case XmlNodeType.Text: xw.WriteString(r.Value); break; default: throw new Exception("Unrecognized node type: " + r.NodeType); } } }
Составляя ответы выше, я обнаружил, что это работает:
private static string FormatXML(string unformattedXml) { // first read the xml ignoring whitespace XmlReaderSettings readeroptions= new XmlReaderSettings {IgnoreWhitespace = true}; XmlReader reader = XmlReader.Create(new StringReader(unformattedXml),readeroptions); // then write it out with indentation StringBuilder sb = new StringBuilder(); XmlWriterSettings xmlSettingsWithIndentation = new XmlWriterSettings { Indent = true}; using (XmlWriter writer = XmlWriter.Create(sb, xmlSettingsWithIndentation)) { writer.WriteNode(reader, true); } return sb.ToString(); }
Я искал ответ на этот вопрос, но в VB.net.
Благодаря Колину Бернетту я решил эту проблему. Я сделал две поправки: во-первых,XmlReaderдолжен игнорировать пробелы (settings.IgnoreWhiteSpaces); во-вторых, читатель должен вернуться в элемент после того, как он прочитает атрибуты. Ниже вы можете увидеть, как выглядит код.Также я пробовал решение GreyCloud, но в сгенерированном XML было несколько раздражающих атрибутов empty (xlmns).
Private Sub PipeXMLIntoWriter(xw As XmlWriter, xml As String) Dim dat As Byte() = New System.Text.UTF8Encoding().GetBytes(xml) Dim m As New MemoryStream() m.Write(dat, 0, dat.Length) m.Seek(0, SeekOrigin.Begin) Dim settings As New XmlReaderSettings settings.IgnoreWhitespace = True settings.IgnoreComments = True Dim r As XmlReader = XmlReader.Create(m, settings) While r.Read() Select Case r.NodeType Case XmlNodeType.Element xw.WriteStartElement(r.Name) If r.HasAttributes Then For i As Integer = 0 To r.AttributeCount - 1 r.MoveToAttribute(i) xw.WriteAttributeString(r.Name, r.Value) Next r.MoveToElement() End If If r.IsEmptyElement Then xw.WriteEndElement() End If Exit Select Case XmlNodeType.EndElement xw.WriteEndElement() Exit Select Case XmlNodeType.Text xw.WriteString(r.Value) Exit Select Case Else Throw New Exception("Unrecognized node type: " + r.NodeType) End Select End While End Sub
Comments