Jak mogę zbudować XML w C #?


438

Jak mogę wygenerować prawidłowy kod XML w języku C #?

Odpowiedzi:


510

To zależy od scenariusza. XmlSerializerjest z pewnością jednym ze sposobów i ma tę zaletę, że mapuje bezpośrednio na model obiektowy. W .NET 3.5 XDocumentitd. Są również bardzo przyjazne. Jeśli rozmiar jest bardzo duży, XmlWriterto twój przyjaciel.

Na XDocumentprzykład:

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

Lub to samo z 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);

Jeśli piszesz duży strumień danych, każde podejście DOM (takie jak XmlDocument/ XDocumentitp.) Szybko zajmie dużo pamięci. Więc jeśli piszesz plik XML 100 MB z CSV , możesz rozważyć XmlWriter; jest to bardziej prymitywne (wężyk jednorazowy zapisu), ale bardzo wydajne (wyobraź sobie dużą pętlę tutaj):

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

Wreszcie przez 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);

To dobry model do mapowania na klasy itp .; jednak może to być przesada, jeśli robisz coś prostego (lub jeśli pożądany kod XML tak naprawdę nie ma bezpośredniej korelacji z modelem obiektowym). Innym problemem XmlSerializerjest to, że nie lubi serializować niezmiennych typów: wszystko musi mieć publiczny getter i setter (chyba że zrobisz to wszystko przez wdrożenie IXmlSerializable, w którym to przypadku nie zyskałeś wiele za pomocą XmlSerializer).


10
Nie zapomnij o XStreamingElement, msdn.microsoft.com/en-us/library/… . :)
Todd White

1
W przykładzie XmlWriter ważne jest, aby pamiętać, że musisz zamknąć program piszący na końcu, aby działał poprawnie - writer.Close () jest potrzebny po funkcji writer.WriteEndElement ().
Marko,

To prawda, co mówi @Marko: Ważne jest, aby poprawnie zamknąć pisarza. Istnieje również inny sposób, aby to zrobić, zamiast bezpośrednio wywoływać writer.Close (). Możesz zawinąć wywołanie Create () w instrukcji using w następujący sposób: using (XmlWriter writer = XmlWriter.Create (Console.Out)) {writer.WriteStartElement („Foo”); itp.} Jest jeszcze inny (nieco bardziej ulepszony) przykład XmlWriter tutaj: dotnetperls.com/xmlwriter
Morten

@Morten Upewnij się, że jeśli XmlWriter implementuje IDisposable, najlepszym rozwiązaniem jest użycie instrukcji.
Marko,

Dobry stary XMLDocument ma to wszystko. Proste, proste i jasne, jeśli tworzysz dokument XML.
FrenkyB

60

Najlepszą rzeczą, jaką wypróbowałem, jest LINQ do XSD (co jest nieznane większości programistów). Dajesz mu schemat XSD, który generuje doskonale odwzorowany kompletny model obiektowy o silnym typie (oparty na LINQ na XML) w tle, który jest naprawdę łatwy w obsłudze - i aktualizuje i weryfikuje twój model obiektowy i XML w czas rzeczywisty. Mimo że nadal jest to „Preview”, nie napotkałem żadnych błędów.

Jeśli masz schemat XSD, który wygląda następująco:

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

Następnie możesz po prostu zbudować XML w następujący sposób:

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

Lub po prostu załaduj XML z pliku w ten sposób:

RootElement rootElement = RootElement.Load(filePath);

Lub zapisz to w ten sposób:

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

rootElement.Untyped zwraca również element w postaci XElement (od LINQ do XML).


wygląda na to, że ten kod nie działa. kiedy chcę to zrobić, nie stosuje się RootElement
żadnej zapisanej funkcji

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

10

XmlWriter to najszybszy sposób na napisanie dobrego XML. XDocument, XMLDocument i niektóre inne działają również dobrze, ale nie są zoptymalizowane do pisania XML. Jeśli chcesz napisać XML tak szybko, jak to możliwe, zdecydowanie powinieneś użyć XmlWriter.


6
To znaczy, jeśli chcesz, aby komputer zapisał XML tak szybko, jak to możliwe. Jeśli Ty, programista, chcesz stworzyć XML w najprostszy i najbardziej naturalny sposób, XmlWriter prawdopodobnie nie jest rozwiązaniem!
sjy


4

Myślę, że ten zasób powinien wystarczyć do umiarkowanego zapisu / załadowania XML: odczyt / zapis XML przy użyciu C # .

Moim zadaniem było przechowywanie notacji muzycznej. Wybieram XML, ponieważ, jak sądzę, .NET jest wystarczająco dojrzały, aby umożliwić łatwe rozwiązanie zadania. Miałem rację :)

Oto prototyp mojego pliku piosenki:

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

Można to rozwiązać dość łatwo:

Aby zapisać do pliku:

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

 }

Aby załadować plik:

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

}
}

1

Dla prostych rzeczy, po prostu używam klas XmlDocument / XmlNode / XmlAttribute i XmlDocument DOM znalezionych w System.XML.

Generuje dla mnie XML, muszę tylko połączyć kilka elementów razem.

Jednak w większych sprawach używam serializacji XML.


1

W prostych przypadkach sugerowałbym także spojrzenie na XmlOutput, płynny interfejs do budowania Xml.

XmlOutput doskonale nadaje się do prostego tworzenia Xml z czytelnym i łatwym do utrzymania kodem, jednocześnie generując prawidłowy Xml. Orginal poczta ma kilka świetnych przykładów.


-3

Jak powyżej.

Używam stringbuilder.append ().

Bardzo proste, a następnie możesz wykonać xmldocument.load (obiekt strinbuilder jako parametr).

Prawdopodobnie znajdziesz się w pliku string.concat w parametrze append, ale jest to bardzo proste podejście.


11
Z wyjątkiem sytuacji, gdy zapomnisz poprawnie zakodować coś i napiszesz nielegalny Xml.
Robert Paulson,

3
Ta odpowiedź została całkowicie odrzucona, ale w oparciu o to pytanie rzuciłem okiem na jedną z moich własnych implementacji, w której buduję XML. W moim konkretnym projekcie konsekwentnie stwierdziłem, że budowanie za pomocą StringBuilder skutkuje czasem przetwarzania o 10% szybszym niż przy użyciu XDocument / XmlWriter. Ale czuję się komfortowo z XML-em i to dotyczy mojego konkretnego projektu. (Dla porównania, końcowe rozmiary XML to około 3,4 MB, z ponad 8000 linii.)
James Skemp

2
Byłbym ciekawy, czy zmierzyłeś kompromis między wydajnością aplikacji (czy mówimy tutaj o milisekundach ulepszeń?) A konserwacją aplikacji (czy Twoi inżynierowie muszą zapoznać się z kodem przez godzinę przed wprowadzeniem zmian?)
Dan Esparza
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.