2009-08-28 11 views
46

De nombreuses fonctions .NET utilisent XmlWriter pour générer/générer des fichiers XML. Sortie à un fichier/string/mémoire est une opération très:Comment créer un XmlDocument en utilisant XmlWriter dans .NET?

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

, parfois vous avez besoin de manipuler le Xml résultant et serait donc à le charger dans un XmlDocument ou peut-être besoin d'un XmlDocument pour une autre raison, mais vous doit générer le XML en utilisant un XmlWriter. Par exemple, si vous appelez une fonction dans une bibliothèque tierce qui renvoie uniquement à un XmlWriter.

L'une des choses que vous pouvez faire est d'écrire le xml à une chaîne, puis le charger dans votre XmlDocument:

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

Cependant cela est inefficace - d'abord vous sérialiser toutes les informations XML dans une chaîne, puis vous allez à nouveau analyser la chaîne pour créer le DOM. Comment pouvez-vous pointer un XmlWriter pour construire un XmlDocument directement?

Comment pouvez-vous pointer un XmlWriter directement pour construire un XmlDocument?

+1

+1 Très bonne question, très utile. – harpo

Répondre

77

Voici au moins une solution:

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. 
} 

Apparemment XpathNavigator vous donne un XmlWriter lorsque vous appelez appendChild()

Crédits vont à Martin Honnen sur : http://groups.google.com/group/microsoft.public.dotnet.xml/browse_thread/thread/24e4c8d249ad8299?pli=1

+1

Bravo, belle trouvaille. –

+1

Merci! Il était évident pour moi que vous seriez capable d'utiliser XmlWriter en tant que constructeur pour XmlDocument mais je ne pouvais pas trouver un moyen facile de le faire, donc j'ai fini par écrire dans le tampon et l'analyse à nouveau. Ils auraient pu le rendre un peu plus facile à trouver. –

+0

Tout le monde sait si la même chose est possible en utilisant xdocument/xelement (en utilisant .NET 3.5 donc ne peux pas charger directement à partir du memorystream) – baileyswalk

9

Vous pouvez faire le contraire: construire la XmlDocument d'abord en utilisant DOM, puis écrire à un XmlWriter:

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

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

Désolé mais cela ne répond pas à la question. J'ai besoin d'utiliser un XmlWriter pour générer le XML - pas un XmlDocument. – Boaz

+4

XmlWriter n'est pas conçu pour écrire dans un XmlDocument, il est conçu pour écrire dans un Stream ou un TextWriter. Ce que vous demandez n'est tout simplement pas possible, je suggère simplement une autre approche ... –

+0

Quoi qu'il en soit, si vous pouvez générer le XML avec un XmlWriter, je ne vois pas pourquoi vous ne pourriez pas le générer avec un XmlDocument. –

4

L'idée derrière XmlWriter est d'attendre jusqu'à ce que vous avez fini de modifier vos données avant de commencer à écrire.

XmlWriter n'a pas été conçu en fonction de votre situation.

Soit

  • Attendez jusqu'à ce que vous savez ce que vos données va être avant d'écrire

ou

  • Faites ce que vous faites actuellement
+4

Je ne suis pas d'accord. XmlWriter est un bon exemple de pattern builder et il est parfaitement logique de l'utiliser pour construire DOM (XmlDocument ou toute autre implémentation). J'ai un cas d'utilisation très réel: Je lis des données XML et les transforme en utilisant XslCompiledTransform, qui écrit dans XmlWriter, qui construit directement XmlDocument, que je peux traiter et ensuite écrire (en appliquant éventuellement un autre XSLT en sortie). Qu'est-ce qui ne va pas avec ça? Et écrire pour streamer puis analyser à nouveau est: a) inutile (cela n'aide pas ou ne rend pas le design plus clair), b) inutile et c) très inefficace. –

1

Il y a un sous-jacent ying Stream objet que le XmlWriter écrivait, s'il était bidirectionnel (MemoryStream), vous pouvez simplement le repositionner à -0- et ensuite utiliser l'objet Stream dans le XmlDocument.Load (stream).

HTH,

Z

+0

Cela entraînerait la même inefficacité - la réparation du flux pour reconstruire un DOM. – Boaz

+0

+1 C'est la façon dont je choisirais de le faire sur l'exemple donné dans la question car une chaîne n'a pas besoin d'être créée en tant qu'intermédiaire. – stevehipwell

+0

Boaz a raison, c'est fondamentalement la même chose que d'analyser le XmlDocument à partir d'une chaîne –

7

Yo Vous pouvez écrire un fichier XML en utilisant la classe XMLWriter. Voici un exemple pour cela.

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