Jak mogę wygenerować prawidłowy kod XML w języku C #?
Jak mogę wygenerować prawidłowy kod XML w języku C #?
Odpowiedzi:
To zależy od scenariusza. XmlSerializer
jest z pewnością jednym ze sposobów i ma tę zaletę, że mapuje bezpośrednio na model obiektowy. W .NET 3.5 XDocument
itd. Są również bardzo przyjazne. Jeśli rozmiar jest bardzo duży, XmlWriter
to twój przyjaciel.
Na XDocument
przykł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
/ XDocument
itp.) 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 XmlSerializer
jest 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
).
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).
RootElement
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.
W przeszłości tworzyłem mój schemat XML, a następnie korzystałem z narzędzia do generowania klas C #, które będą serializować do tego schematu. Narzędzie do definiowania schematów XML jest jednym przykładem
http://msdn.microsoft.com/en-us/library/x6c1kb0s(VS.71).aspx
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);
}
}
}
}
}
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.
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.