Comment puis-je créer du XML en C #?

438

Comment puis-je générer du XML valide en C #?

Dan Esparza
la source

Réponses:

510

Cela dépend du scénario. XmlSerializerest certainement un moyen et a l'avantage de correspondre directement à un modèle d'objet. Dans .NET 3.5, XDocumentetc. sont également très conviviaux. Si la taille est très grande, alors XmlWriterc'est votre ami.

Pour un XDocumentexemple:

Console.WriteLine(
    new XElement("Foo",
        new XAttribute("Bar", "some & value"),
        new XElement("Nested", "data")));

Ou la même chose avec XmlDocument:

XmlDocument doc = new XmlDocument();
XmlElement el = (XmlElement)doc.AppendChild(doc.CreateElement("Foo"));
el.SetAttribute("Bar", "some & value");
el.AppendChild(doc.CreateElement("Nested")).InnerText = "data";
Console.WriteLine(doc.OuterXml);

Si vous écrivez un grand flux de données, l'une des approches DOM (telles que XmlDocument/ XDocument, etc.) prendra rapidement beaucoup de mémoire. Donc, si vous écrivez un fichier XML de 100 Mo à partir de CSV , vous pourriez envisager XmlWriter; c'est plus primitif (un firehose à écriture unique), mais très efficace (imaginez une grosse boucle ici):

XmlWriter writer = XmlWriter.Create(Console.Out);
writer.WriteStartElement("Foo");
writer.WriteAttributeString("Bar", "Some & value");
writer.WriteElementString("Nested", "data");
writer.WriteEndElement();

Enfin, via XmlSerializer :

[Serializable]
public class Foo
{
    [XmlAttribute]
    public string Bar { get; set; }
    public string Nested { get; set; }
}
...
Foo foo = new Foo
{
    Bar = "some & value",
    Nested = "data"
};
new XmlSerializer(typeof(Foo)).Serialize(Console.Out, foo);

C'est un joli modèle pour le mappage aux classes, etc .; cependant, il peut être exagéré si vous faites quelque chose de simple (ou si le XML souhaité n'a pas vraiment de corrélation directe avec le modèle d'objet). Un autre problème XmlSerializerest qu'il n'aime pas sérialiser les types immuables: tout doit avoir un getter et un setter publics (à moins que vous ne fassiez tout vous-même en implémentant IXmlSerializable, auquel cas vous n'avez pas beaucoup gagné en utilisant XmlSerializer).

Marc Gravell
la source
10
N'oubliez pas XStreamingElement, msdn.microsoft.com/en-us/library/… . :)
Todd White
1
Pour l'exemple XmlWriter, il est important de noter que vous devez fermer le rédacteur à la fin pour qu'il fonctionne correctement - writer.Close () est nécessaire après le writer.WriteEndElement ().
Marko
C'est vrai ce que dit @Marko: Il est important de fermer correctement le rédacteur. Il existe également une autre façon de procéder, au lieu d'appeler directement writer.Close (). Vous pouvez encapsuler l'appel à Create () dans une instruction using comme celle-ci: using (XmlWriter writer = XmlWriter.Create (Console.Out)) {writer.WriteStartElement ("Foo"); etc} Il y a un autre exemple (un peu plus amélioré) de XmlWriter ici: dotnetperls.com/xmlwriter
Morten
@Morten Bien sûr, si XmlWriter implémente l'IDisposable, alors l'utilisation de l'instruction est la meilleure option.
Marko
Le bon vieux XMLDocument a tout. Droit, simple et clair si vous créez un document XML.
FrenkyB
60

La meilleure chose que j'ai essayé de loin est LINQ to XSD (qui est inconnu de la plupart des développeurs). Vous lui donnez un schéma XSD et il génère un modèle d'objet complet fortement typé parfaitement mappé (basé sur LINQ to XML) pour vous en arrière-plan, ce qui est vraiment facile à travailler - et il met à jour et valide votre modèle d'objet et XML dans temps réel. Bien qu'il soit toujours "Aperçu", je n'ai rencontré aucun bogue avec.

Si vous avez un schéma XSD qui ressemble à ceci:

  <xs:element name="RootElement">
     <xs:complexType>
      <xs:sequence>
        <xs:element name="Element1" type="xs:string" />
        <xs:element name="Element2" type="xs:string" />
      </xs:sequence>
       <xs:attribute name="Attribute1" type="xs:integer" use="optional" />
       <xs:attribute name="Attribute2" type="xs:boolean" use="required" />
     </xs:complexType>
  </xs:element>

Ensuite, vous pouvez simplement créer du XML comme ceci:

RootElement rootElement = new RootElement;
rootElement.Element1 = "Element1";
rootElement.Element2 = "Element2";
rootElement.Attribute1 = 5;
rootElement.Attribute2 = true;

Ou chargez simplement un XML à partir d'un fichier comme celui-ci:

RootElement rootElement = RootElement.Load(filePath);

Ou enregistrez-le comme ceci:

rootElement.Save(string);
rootElement.Save(textWriter);
rootElement.Save(xmlWriter);

rootElement.Untyped donne également l'élément sous la forme d'un XElement (de LINQ à XML).

65199
la source
semble que ce code ne fonctionne pas. quand je dois faire comme ça il n'y a pas de fucntion de sauvegarde appliquéeRootElement
DanilGholtsman
24
new XElement("Foo",
       from s in nameValuePairList
       select
             new XElement("Bar",
                  new XAttribute("SomeAttr", "SomeAttrValue"),
                          new XElement("Name", s.Name),
                          new XElement("Value", s.Value)
                         )
            );
Vincent
la source
10

XmlWriter est le moyen le plus rapide d'écrire du bon XML. XDocument, XMLDocument et quelques autres fonctionnent également bien, mais ne sont pas optimisés pour l'écriture XML. Si vous souhaitez écrire le XML le plus rapidement possible, vous devez absolument utiliser XmlWriter.

Mikael Söderström
la source
6
Autrement dit, si vous souhaitez que l' ordinateur écrive le XML le plus rapidement possible. Si vous, le développeur, souhaitez créer XML de la manière la plus simple et la plus naturelle, XmlWriter n'est probablement pas la solution!
2014
4

Je pense que cette ressource devrait suffire pour une sauvegarde / charge XML modérée: lecture / écriture XML en utilisant C # .

Ma tâche était de stocker la notation musicale. Je choisis XML, car je suppose que .NET a suffisamment mûri pour permettre une solution facile pour la tâche. J'avais raison :)

Voici mon prototype de fichier de chanson:

<music judul="Kupu-Kupu yang Lucu" pengarang="Ibu Sud" tempo="120" birama="4/4" nadadasar="1=F" biramapembilang="4" biramapenyebut="4">
    <not angka="1" oktaf="0" naikturun="" nilai="1"/>
    <not angka="2" oktaf="0" naikturun="" nilai="0.5"/>
    <not angka="5" oktaf="1" naikturun="/" nilai="0.25"/>
    <not angka="2" oktaf="0" naikturun="\" nilai="0.125"/>
    <not angka="1" oktaf="0" naikturun="" nilai="0.0625"/>
</music>

Cela peut être résolu assez facilement:

Pour enregistrer dans un fichier:

 private void saveToolStripMenuItem_Click(object sender, EventArgs e)
 {
     saveFileDialog1.Title = "Save Song File";
     saveFileDialog1.Filter = "Song Files|*.xsong";
     if (saveFileDialog1.ShowDialog() == DialogResult.OK)
     {
         FileStream fs = new FileStream(saveFileDialog1.FileName, FileMode.Create);
         XmlTextWriter w = new XmlTextWriter(fs, Encoding.UTF8);
         w.WriteStartDocument();
         w.WriteStartElement("music");
         w.WriteAttributeString("judul", Program.music.getTitle());
         w.WriteAttributeString("pengarang", Program.music.getAuthor());
         w.WriteAttributeString("tempo", Program.music.getTempo()+"");
         w.WriteAttributeString("birama", Program.music.getBirama());
         w.WriteAttributeString("nadadasar", Program.music.getNadaDasar());
         w.WriteAttributeString("biramapembilang", Program.music.getBiramaPembilang()+"");
         w.WriteAttributeString("biramapenyebut", Program.music.getBiramaPenyebut()+"");

         for (int i = 0; i < listNotasi.Count; i++)
         {
             CNot not = listNotasi[i];
             w.WriteStartElement("not");
             w.WriteAttributeString("angka", not.getNot() + "");
             w.WriteAttributeString("oktaf", not.getOktaf() + "");
             String naikturun="";
             if(not.isTurunSetengah())naikturun="\\";
             else if(not.isNaikSetengah())naikturun="/";
             w.WriteAttributeString("naikturun",naikturun);
             w.WriteAttributeString("nilai", not.getNilaiNot()+"");
             w.WriteEndElement();
         }
         w.WriteEndElement();

         w.Flush();
         fs.Close();
     }

 }

Pour charger le fichier:

openFileDialog1.Title = "Open Song File";
openFileDialog1.Filter = "Song Files|*.xsong";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
    FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open);
    XmlTextReader r = new XmlTextReader(fs);

    while (r.Read())
    {
        if (r.NodeType == XmlNodeType.Element)
        {
            if (r.Name.ToLower().Equals("music"))
            {
                Program.music = new CMusic(r.GetAttribute("judul"),
                    r.GetAttribute("pengarang"),
                    r.GetAttribute("birama"),
                    Convert.ToInt32(r.GetAttribute("tempo")),
                    r.GetAttribute("nadadasar"),
                    Convert.ToInt32(r.GetAttribute("biramapembilang")),
                    Convert.ToInt32(r.GetAttribute("biramapenyebut")));
            }
            else
                if (r.Name.ToLower().Equals("not"))
                {
                    CNot not = new CNot(Convert.ToInt32(r.GetAttribute("angka")), Convert.ToInt32(r.GetAttribute("oktaf")));
                    if (r.GetAttribute("naikturun").Equals("/"))
                    {
                        not.setNaikSetengah();
                    }
                    else if (r.GetAttribute("naikturun").Equals("\\"))
                    {
                        not.setTurunSetengah();
                    }
                    not.setNilaiNot(Convert.ToSingle(r.GetAttribute("nilai")));
                    listNotasi.Add(not);
                }
        }
        else
            if (r.NodeType == XmlNodeType.Text)
            {
                Console.WriteLine("\tVALUE: " + r.Value);
            }
    }
}

}
}
swdev
la source
1

Pour des choses simples, j'utilise simplement les classes XmlDocument / XmlNode / XmlAttribute et XmlDocument DOM trouvés dans System.XML.

Il génère le XML pour moi, j'ai juste besoin de lier quelques éléments ensemble.

Cependant, sur des choses plus importantes, j'utilise la sérialisation XML.

FlySwat
la source
1

Pour les cas simples, je suggère également de regarder XmlOutput une interface fluide pour construire Xml.

XmlOutput est idéal pour la création de Xml simple avec du code lisible et maintenable, tout en générant du Xml valide. Le post original a de bons exemples.

Todd
la source
-3

Comme ci-dessus.

J'utilise stringbuilder.append ().

Très simple, et vous pouvez ensuite faire xmldocument.load (objet strinbuilder comme paramètre).

Vous vous retrouverez probablement à utiliser string.concat dans le paramètre append, mais c'est une approche très simple.

GurdeepS
la source
11
Sauf lorsque vous oubliez de coder quelque chose correctement et d'écrire du Xml illégal.
Robert Paulson
3
Cette réponse a été absolument critiquée, mais sur la base de cette question, j'ai jeté un coup d'œil à l'une de mes propres implémentations où je construis XML. Pour mon projet particulier, j'ai toujours constaté que la construction via StringBuilder entraînait des temps de traitement 10% plus rapides que l'utilisation de XDocument / XmlWriter. Mais, je me sens à l'aise avec XML, et c'est pour mon projet particulier. (Pour référence, les tailles XML finales sont d'environ 3,4 Mo, avec plus de 8000 lignes.)
James Skemp
2
Je serais curieux de savoir si vous avez mesuré le compromis entre les performances des applications (parlons-nous d'améliorations en millisecondes ici?) Et la maintenance des applications (vos ingénieurs doivent-ils se familiariser avec le code pendant une heure avant d'apporter des modifications maintenant?)
Dan Esparza