2009-08-28 12 views
46

Muchas funciones .NET usan XmlWriter para generar/generar xml. Enviar a un archivo/cadena/de memoria es una operación misma:¿Cómo crear un XmlDocument usando XmlWriter en .NET?

XmlWriter xw = XmlWriter.Create(PutYourStreamFileWriterEtcHere); 
xw.WriteStartElement("root"); 
... 

A veces, es necesario manipular el XML resultante y por lo tanto desea cargar en un XmlDocument o que necesiten un XmlDocument por alguna otra razón, pero debe generar el XML usando un XmlWriter. Por ejemplo, si llama a una función en una biblioteca de terceros que solo imprime en un XmlWriter.

Una de las cosas que puede hacer es escribir el código XML en una cadena y luego cargarla en su XmlDocument:

StringWriter S = new StringWriter(); 
XmlWriter xw = XmlWriter.Create(S); 
/* write away */ 
XmlDocument xdoc = new XmlDocument(); 
xdoc.LoadXml(S.ToString()); 

Sin embargo, esto es ineficiente - primera serializar toda la información XML en una cadena, a continuación, analiza la cadena de nuevo para crear el DOM.

¿Cómo se puede apuntar un XmlWriter para construir un XmlDocument directamente?

+1

+1 Gran pregunta, muy útil. – harpo

Respuesta

77

Aquí es al menos una solución:

XmlDocument doc = new XmlDocument(); 
using (XmlWriter writer = doc.CreateNavigator().AppendChild()) 
{ 
    // Do this directly 
    writer.WriteStartDocument(); 
    writer.WriteStartElement("root"); 
    writer.WriteElementString("foo", "bar"); 
    writer.WriteEndElement(); 
    writer.WriteEndDocument(); 
    // or anything else you want to with writer, like calling functions etc. 
} 

Al parecer XpathNavigator le da una XmlWriter cuando llame AppendChild()

Los créditos van a Martin Honnen en : http://groups.google.com/group/microsoft.public.dotnet.xml/browse_thread/thread/24e4c8d249ad8299?pli=1

+1

Bien hecho, buen descubrimiento. –

+1

Gracias! Era obvio para mí que podrías utilizar XmlWriter como constructor para XmlDocument, pero no pude encontrar una manera fácil de hacerlo, así que terminé escribiendo en el búfer y el análisis de nuevo. Podrían haberlo hecho un poco más fácil de encontrar. –

+0

Cualquiera sabe si lo mismo es posible usando xdocument/xelement (usando .NET 3.5, por lo tanto no se puede cargar directamente desde la corriente de memoria) – baileyswalk

9

que podría hacer lo contrario: construir el XmlDocument primero usando DOM, y luego escribirla en un XmlWriter:

XmlDocument xdoc = new XmlDocument(); 
... // build the document 

StringWriter S = new StringWriter(); 
XmlWriter xw = XmlWriter.Create(S); 
xdoc.WriteTo(xw); 
+0

Lo siento pero esto no responde la pregunta. Necesito usar un XmlWriter para generar el XML, no un XmlDocument. – Boaz

+4

XmlWriter no está diseñado para escribir en XmlDocument, está diseñado para escribir en Stream o TextWriter. Lo que estás preguntando simplemente no es posible, solo sugiero otro enfoque ... –

+0

De todos modos, si puedes generar el XML con un XmlWriter, no veo por qué no podrías generarlo con un XmlDocument ... –

4

La idea detrás de XmlWriter es esperar hasta que haya terminado de modificar sus datos antes de empezar a escribir.

XmlWriter no se creó teniendo en cuenta su situación.

De cualquier

  • Esperar hasta que sepa lo que sus datos se va a ser antes de escribir

o

  • hacer lo que está haciendo actualmente
+4

No estoy de acuerdo. XmlWriter es un buen ejemplo de patrón de generador y tiene mucho sentido usarlo para compilar DOM (XmlDocument o cualquier otra implementación). Y tengo un caso de uso muy real: Leo datos XML y los transformo usando XslCompiledTransform, que escribe en XmlWriter, que construye directamente XmlDocument, que puedo procesar y luego escribir (posiblemente aplicando algún otro XSLT en la salida). ¿Qué está mal con eso? Y escribir para transmitir y luego volver a analizar es: a) inútil (no ayuda o hace que el diseño sea más claro), b) innecesario yc) altamente ineficiente. –

1

Hay un underl ying El objeto Stream en el que el XmlWriter estaba escribiendo, si fuera bidireccional (MemoryStream), simplemente podría volver a colocarlo en -0- y luego usar el objeto Stream en XmlDocument.Load (stream).

HTH,

Z

+0

Esto daría como resultado la misma ineficacia: reparsing la secuencia para construir un DOM nuevamente. – Boaz

+0

+1 Esta es la forma en que elegiría hacerlo sobre el ejemplo dado en la pregunta, ya que una cadena no necesita ser creada como un intermediario. – stevehipwell

+0

Boaz tiene razón, es básicamente lo mismo que analizar el XmlDocument desde una cadena –

7

Yo Puedes escribir un archivo xml usando la clase XMLWriter. Aquí hay un ejemplo para esto.

XmlWriterSettings objSetting = new XmlWriterSettings(); 
    objSetting.Indent = true; 
    objSetting.NewLineOnAttributes = true; 

    System.Text.StringBuilder sb = new System.Text.StringBuilder(); 


    using (XmlWriter objWriter = XmlWriter.Create(sb, objSetting)) 
    { 
     //Note the artificial, but useful, indenting 
     objWriter.WriteStartDocument(); 

     objWriter.WriteStartElement("books"); 

     ////////Start Book Element/////// 

     objWriter.WriteStartElement("book"); 

     objWriter.WriteStartAttribute("ISBN"); 
     objWriter.WriteValue("asp1"); 
     objWriter.WriteEndAttribute(); 

     objWriter.WriteStartElement("Title"); 
     objWriter.WriteValue("ASP.NET"); 
     objWriter.WriteEndElement(); 

     objWriter.WriteElementString("ReleaseDate", "11/11/2010"); 

     objWriter.WriteStartElement("Pages"); 
     objWriter.WriteValue(200); 
     objWriter.WriteEndElement(); //price 

     objWriter.WriteEndElement(); //book 
     ////////End Book Element/////// 


     ////////Another Element 

     ////////Start Book Element/////// 

     objWriter.WriteStartElement("book"); 

     objWriter.WriteStartAttribute("ISBN"); 
     objWriter.WriteValue("c#2"); 
     objWriter.WriteEndAttribute(); 

     objWriter.WriteStartElement("Title"); 
     objWriter.WriteValue("C#.NET"); 
     objWriter.WriteEndElement(); 

     objWriter.WriteElementString("ReleaseDate", "10/11/2010"); 

     objWriter.WriteStartElement("Pages"); 
     objWriter.WriteValue(500); 
     objWriter.WriteEndElement(); 

     objWriter.WriteEndElement(); //book 
     ////////End Book Element/////// 



     objWriter.WriteEndElement(); //books 
     objWriter.WriteEndDocument(); 

    } 

    File.WriteAllText(Server.MapPath("BooksList.xml"), sb.ToString()); 
Cuestiones relacionadas