net ejemplo c# .net xml

net - xmldocument c# ejemplo



La sangrĂ­a XML al inyectar una cadena XML en un XmlWriter (6)

Tengo un XmlTextWriter escribiendo en un archivo y un XmlWriter usando ese escritor de texto. Este escritor de texto está configurado para generar XML con sangría de tabulación:

XmlTextWriter xtw = new XmlTextWriter("foo.xml", Encoding.UTF8); xtw.Formatting = Formatting.Indented; xtw.IndentChar = ''/t''; xtw.Indentation = 1; XmlWriter xw = XmlWriter.Create(xtw);

Cambiado por el enlace de MSDN de Jeff:

XmlWriterSettings set = new XmlWriterSettings(); set.Indent = true; set.IndentChars = "/t"; set.Encoding = Encoding.UTF8; xw = XmlWriter.Create(f, set);

Esto no cambia el resultado final.

Ahora tengo una profundidad arbitraria en mi XmlWriter y obtengo una cadena de XML de otro lugar (que no puedo controlar) que es un XML de una sola línea, sin sangría. Si llamo xw.WriteRaw (), esa cadena se inyecta literalmente y no sigue la sangría que quiero.

... string xml = ExternalMethod(); xw.WriteRaw(xml); ...

Esencialmente, quiero un WriteRaw que analice la cadena XML y pase por todo el WriteStartElement, etc. para que se reformatee según la configuración de XmlTextWriter''s.

Mi preferencia es una forma de hacer esto con la configuración que ya tengo y hacerlo sin tener que volver a cargar el XML final solo para reformatearlo. También preferiría no analizar la cadena XML con los gustos de XmlReader y luego imitar lo que encuentra en mi XmlWriter (proceso muy manual).

Al final de esto, prefiero tener una solución simple que una que siga mis preferencias. (Naturalmente, la mejor solución sería simple y sigue mis preferencias).


¿Qué hay de usar un XmlReader para leer el xml como nodos xml?

string xml = ExternalMethod(); XmlReader reader = XmlReader.Create(new StringReader(xml)); xw.WriteNode(reader, true);


Estaba buscando una respuesta a este problema pero en VB.net.

Gracias a Colin Burnett, lo resolví. Hice dos correcciones: primero, XmlReader debe ignorar los espacios en blanco ( settings.IgnoreWhiteSpaces ); En segundo lugar, el lector debe volver al elemento después de leer los atributos. A continuación puedes ver cómo se ve el código.

También probé la solución de GreyCloud, pero en el XML generado había algunos atributos de vacíos molestos (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


Esto es lo mejor que tengo hasta ahora. Un proceso muy manual que solo soporta lo que está escrito. Mi cadena XML no es más que etiquetas, atributos y datos de texto. Si admitiera espacios de nombres, CDATA, etc., entonces esto tendría que crecer en consecuencia.

Muy manual, muy desordenado y muy propenso a los errores, pero cumple con mis preferencias.

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); } } }


No debe usar XmlTextWriter , como se indica en MSDN donde dice:

En la versión 2.0 de .NET Framework, la práctica recomendada es crear instancias de XmlWriter usando el método XmlWriter.Create y la clase XmlWriterSettings. Esto le permite aprovechar al máximo todas las nuevas características introducidas en esta versión. Para obtener más información, consulte Crear escritores XML.

En su lugar, debes usar XmlWriter.Create para obtener tu escritor. Luego puedes usar la clase XmlWriterSettings para especificar cosas como la sangría.

XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = "/t";

Actualizar

Creo que puedes usar WriteNode. Toma su cadena xml y la carga en un XDocument o XmlReader y luego usa el nodo para escribirla en su XmlWriter.


Qué tal si:

string xml = ExternalMethod(); var xd = XDocument.Parse(xml); xd.WriteTo(xw);


componiendo las respuestas anteriores he encontrado este trabajo:

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(); }