Wie kann ich XML in C # erstellen?

438

Wie kann ich gültiges XML in C # generieren?

Dan Esparza
quelle

Antworten:

510

Das hängt vom Szenario ab. XmlSerializerist sicherlich eine Möglichkeit und hat den Vorteil, direkt auf ein Objektmodell abzubilden. In .NET 3.5 XDocumentusw. sind auch sehr freundlich. Wenn die Größe sehr groß ist, dann XmlWriterist dein Freund.

Ein XDocumentBeispiel:

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

Oder das gleiche mit 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);

Wenn Sie einen großen Datenstrom schreiben , beansprucht jeder der DOM-Ansätze (wie XmlDocument/ XDocumentusw.) schnell viel Speicher. Wenn Sie also eine 100-MB-XML-Datei aus CSV schreiben , sollten Sie dies in Betracht ziehen XmlWriter. Dies ist primitiver (ein einmal geschriebener Feuerwehrschlauch), aber sehr effizient (stellen Sie sich hier eine große Schleife vor):

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

Zum Schluss über 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);

Dies ist ein schönes Modell für die Zuordnung zu Klassen usw.; Es kann jedoch zu viel des Guten sein, wenn Sie etwas Einfaches tun (oder wenn das gewünschte XML keine direkte Korrelation zum Objektmodell hat). Ein weiteres Problem XmlSerializerist, dass unveränderliche Typen nicht gerne serialisiert werden: Alles muss einen öffentlichen Getter und Setter haben (es sei denn, Sie tun alles selbst durch Implementierung IXmlSerializable, in diesem Fall haben Sie durch die Verwendung nicht viel gewonnen XmlSerializer).

Marc Gravell
quelle
10
Vergessen Sie nicht XStreamingElement, msdn.microsoft.com/en-us/library/… . :)
Todd White
1
Für das XmlWriter-Beispiel ist es wichtig zu beachten, dass Sie den Writer am Ende schließen müssen, damit er ordnungsgemäß funktioniert. Writer.Close () wird nach dem Writer benötigt.WriteEndElement ().
Marko
Es ist wahr, was @Marko sagt: Es ist wichtig, den Autor richtig zu schließen. Es gibt auch eine andere Möglichkeit, dies zu tun, anstatt writer.Close () direkt aufzurufen. Sie können den Aufruf von Create () in eine using-Anweisung wie folgt einschließen: using (XmlWriter writer = XmlWriter.Create (Console.Out)) {writer.WriteStartElement ("Foo"); etc} Es gibt ein weiteres (etwas erweitertes) Beispiel für XmlWriter hier: dotnetperls.com/xmlwriter
Morten
@Morten Sicher, wenn XmlWriter das IDisposable implementiert, ist die Verwendung der Anweisung die beste Option.
Marko
Gutes altes XMLDocument hat alles. Einfach, klar und deutlich, wenn Sie ein XML-Dokument erstellen.
FrenkyB
60

Das Beste, was ich je versucht habe, ist LINQ to XSD (was den meisten Entwicklern unbekannt ist). Sie geben ihm ein XSD-Schema und es generiert im Hintergrund ein perfekt zugeordnetes vollständiges stark typisiertes Objektmodell (basierend auf LINQ to XML), mit dem Sie sehr einfach arbeiten können - und es aktualisiert und validiert Ihr Objektmodell und XML in Echtzeit. Während es noch "Vorschau" ist, habe ich keine Fehler damit festgestellt.

Wenn Sie ein XSD-Schema haben, das folgendermaßen aussieht:

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

Dann können Sie einfach XML wie folgt erstellen:

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

Oder laden Sie einfach ein XML aus einer Datei wie folgt:

RootElement rootElement = RootElement.Load(filePath);

Oder speichern Sie es so:

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

rootElement.Untyped liefert das Element auch in Form eines XElement (von LINQ bis XML).

Benutzer65199
quelle
Anscheinend funktioniert dieser Code nicht. Wenn ich so etwas machen möchte, wird keine Save-Funktion angewendetRootElement
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
quelle
10

XmlWriter ist der schnellste Weg, um gutes XML zu schreiben. XDocument, XMLDocument und einige andere funktionieren ebenfalls gut, sind jedoch nicht für das Schreiben von XML optimiert. Wenn Sie das XML so schnell wie möglich schreiben möchten, sollten Sie auf jeden Fall XmlWriter verwenden.

Mikael Söderström
quelle
6
Das heißt, wenn Sie möchten, dass der Computer das XML so schnell wie möglich schreibt. Wenn Sie als Entwickler XML auf einfachste und natürlichste Weise erstellen möchten, ist XmlWriter wahrscheinlich nicht die Lösung!
Sjy
4

Ich denke, diese Ressource sollte für ein moderates Speichern / Laden von XML ausreichen: Lesen / Schreiben von XML mit C # .

Meine Aufgabe war es, Noten zu speichern. Ich habe mich für XML entschieden, weil .NET vermutlich so ausgereift ist, dass eine einfache Lösung für die Aufgabe möglich ist. Ich lag richtig :)

Dies ist mein Prototyp der Songdatei:

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

Das lässt sich ganz einfach lösen:

Zum Speichern in Datei:

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

 }

Zum Laden der Datei:

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
quelle
1

Für einfache Dinge verwende ich einfach die Klassen XmlDocument / XmlNode / XmlAttribute und XmlDocument DOM in System.XML.

Es generiert das XML für mich, ich muss nur ein paar Elemente miteinander verknüpfen.

Bei größeren Dingen verwende ich jedoch die XML-Serialisierung.

FlySwat
quelle
1

Für einfache Fälle würde ich auch empfehlen, sich XmlOutput als fließende Schnittstelle zum Erstellen von Xml anzusehen .

XmlOutput eignet sich hervorragend für die einfache Erstellung von XML mit lesbarem und wartbarem Code, während gültige XML-Dateien generiert werden. Der ursprüngliche Beitrag enthält einige großartige Beispiele.

Todd
quelle
-3

Wie oben.

Ich benutze stringbuilder.append ().

Sehr einfach, und Sie können dann xmldocument.load (strinbuilder-Objekt als Parameter) ausführen.

Sie werden wahrscheinlich feststellen, dass Sie string.concat im Parameter append verwenden, dies ist jedoch ein sehr einfacher Ansatz.

GurdeepS
quelle
11
Außer wenn Sie vergessen, etwas richtig zu codieren und illegale XML-Dateien zu schreiben.
Robert Paulson
3
Diese Antwort wurde absolut kritisiert, aber basierend auf dieser Frage habe ich mir eine meiner eigenen Implementierungen angesehen, in denen ich XML erstelle. Bei meinem speziellen Projekt stellte ich immer wieder fest, dass das Erstellen über StringBuilder zu Verarbeitungszeiten führte, die 10% schneller waren als mit XDocument / XmlWriter. Aber ich fühle mich mit XML wohl, und das ist für mein spezielles Projekt. (Als Referenz liegen die endgültigen XML-Größen bei etwa 3,4 MB mit über 8000 Zeilen.)
James Skemp
2
Ich wäre gespannt, ob Sie den Kompromiss zwischen Anwendungsleistung (sprechen wir hier von Millisekunden-Verbesserungen?) Und Anwendungswartung (müssen sich Ihre Ingenieure eine Stunde lang mit dem Code vertraut machen, bevor Sie Änderungen vornehmen?)
Dan Esparza