¿Cómo puedo construir XML en C #?

438

¿Cómo puedo generar XML válido en C #?

Dan Esparza
fuente

Respuestas:

510

Depende del escenario. XmlSerializerSin duda es una forma y tiene la ventaja de mapear directamente a un modelo de objeto. En .NET 3.5, XDocumentetc. también son muy amigables. Si el tamaño es muy grande, entonces XmlWriteres tu amigo.

Por un XDocumentejemplo:

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

O lo mismo con 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 está escribiendo una gran secuencia de datos, cualquiera de los enfoques DOM (como XmlDocument/ XDocument, etc.) ocupará rápidamente mucha memoria. Entonces, si está escribiendo un archivo XML de 100 MB desde CSV , puede considerar XmlWriter; Esto es más primitivo (una manguera de incendios de escritura única), pero muy eficiente (imagine un gran bucle aquí):

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

Finalmente, a través de 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);

Este es un buen modelo para mapear a clases, etc .; sin embargo, podría ser excesivo si está haciendo algo simple (o si el XML deseado realmente no tiene una correlación directa con el modelo de objetos). Otro problema XmlSerializeres que no le gusta serializar los tipos inmutables: todo debe tener un captador y configurador público (a menos que lo haga todo usted mismo mediante la implementación IXmlSerializable, en cuyo caso no ha ganado mucho al usarlo XmlSerializer).

Marc Gravell
fuente
10
No se olvide de XStreamingElement, msdn.microsoft.com/en-us/library/… . :)
Todd White el
1
Para el ejemplo de XmlWriter, es importante tener en cuenta que debe cerrar el escritor al final para que funcione correctamente: se necesita writer.Close () después del escritor.WriteEndElement ().
Marko
Es cierto lo que dice @Marko: es importante cerrar el escritor correctamente. También hay otra forma de hacerlo, en lugar de llamar a writer.Close () directamente. Puede ajustar la llamada a Create () en una instrucción de uso como esta: using (XmlWriter writer = XmlWriter.Create (Console.Out)) {writer.WriteStartElement ("Foo"); etc} Aquí hay otro ejemplo (un poco más mejorado) de XmlWriter: dotnetperls.com/xmlwriter
Morten
@Morten Claro que si XmlWriter implementa el IDisposable, entonces usar la declaración es la mejor opción.
Marko
El viejo y bueno XMLDocument lo tiene todo. Directo, simple y claro si está creando un documento XML.
FrenkyB
60

Lo mejor que he probado es LINQ to XSD (que la mayoría de los desarrolladores desconocen). Le da un esquema XSD y genera un modelo de objeto completo fuertemente tipado perfectamente mapeado (basado en LINQ to XML) para usted en segundo plano, que es realmente fácil de trabajar, y actualiza y valida su modelo de objeto y XML en tiempo real. Si bien todavía es "Vista previa", no he encontrado ningún error con él.

Si tiene un esquema XSD que se ve así:

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

Entonces puedes simplemente crear XML de esta manera:

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

O simplemente cargue un XML desde un archivo como este:

RootElement rootElement = RootElement.Load(filePath);

O guárdelo así:

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

rootElement.Untyped también produce el elemento en forma de XElement (de LINQ a XML).

usuario65199
fuente
Parece que este código no funciona. cuando intento hacer esto, no se aplica ninguna función de guardarRootElement
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
fuente
10

XmlWriter es la forma más rápida de escribir un buen XML. XDocument, XMLDocument y algunos otros también funcionan bien, pero no están optimizados para escribir XML. Si desea escribir el XML lo más rápido posible, definitivamente debe usar XmlWriter.

Mikael Söderström
fuente
66
Es decir, si desea que la computadora escriba el XML lo más rápido posible. Si usted, el desarrollador, desea crear XML de la manera más fácil y natural, ¡XmlWriter probablemente no sea la solución!
sjy
4

Creo que este recurso debería ser suficiente para guardar / cargar XML moderadamente: leer / escribir XML usando C # .

Mi tarea era almacenar la notación musical. Elijo XML, porque supongo que .NET ha madurado lo suficiente como para permitir una solución fácil para la tarea. Yo tenía razón :)

Este es mi prototipo de archivo de canción:

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

Eso se puede resolver con bastante facilidad:

Para guardar en archivo:

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

 }

Para cargar archivo:

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

Para cosas simples, solo uso las clases XmlDocument / XmlNode / XmlAttribute y XmlDocument DOM que se encuentran en System.XML.

Genera el XML para mí, solo necesito vincular algunos elementos.

Sin embargo, en cosas más grandes, uso la serialización XML.

FlySwat
fuente
1

Para casos simples, también sugeriría buscar en XmlOutput una interfaz fluida para construir Xml.

XmlOutput es ideal para la creación simple de Xml con código legible y mantenible, mientras genera Xml válido. La publicación original tiene algunos excelentes ejemplos.

Todd
fuente
-3

Como anteriormente.

Yo uso stringbuilder.append ().

Muy sencillo, y luego puede hacer xmldocument.load (objeto strinbuilder como parámetro).

Probablemente se encontrará utilizando string.concat dentro del parámetro append, pero este es un enfoque muy sencillo.

GurdeepS
fuente
11
Excepto cuando olvides codificar algo correctamente y escribir Xml ilegal.
Robert Paulson el
3
Esta respuesta se cerró de golpe, pero en base a esta pregunta eché un vistazo a una de mis propias implementaciones donde construyo XML. Para mi proyecto en particular, siempre encontré que construir a través de StringBuilder resultó en tiempos de procesamiento 10% más rápidos que usar XDocument / XmlWriter. Pero, me siento cómodo con XML, y eso es para mi proyecto particular. (Como referencia, los tamaños XML finales son de alrededor de 3,4 MB, con más de 8000 líneas.)
James Skemp
2
Me gustaría saber si midió el equilibrio entre el rendimiento de la aplicación (¿estamos hablando de mejoras de milisegundos aquí?) Y el mantenimiento de la aplicación (¿necesitan sus ingenieros familiarizarse con el código durante una hora antes de realizar cambios ahora?)
Dan Esparza