Como posso criar XML em c #?

438

Como posso gerar XML válido em c #?

Dan Esparza
fonte

Respostas:

510

Depende do cenário. XmlSerializeré certamente uma maneira e tem a vantagem de mapear diretamente para um modelo de objeto. No .NET 3.5, XDocumentetc. também são muito amigáveis. Se o tamanho é muito grande, então XmlWriteré seu amigo.

Por XDocumentexemplo:

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

Ou o mesmo com 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);

Se você estiver gravando um grande fluxo de dados, qualquer uma das abordagens do DOM (como XmlDocument/ XDocument, etc.) consumirá rapidamente muita memória. Portanto, se você estiver gravando um arquivo XML de 100 MB a partir do CSV , considere XmlWriter; isso é mais primitivo (uma mangueira de fogo de gravação única), mas muito eficiente (imagine um grande loop aqui):

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

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

Este é um bom modelo para mapear para classes, etc .; no entanto, pode ser um exagero se você estiver fazendo algo simples (ou se o XML desejado realmente não tiver uma correlação direta com o modelo de objeto). Outro problema XmlSerializeré que ele não gosta de serializar tipos imutáveis: tudo deve ter um getter e setter públicos (a menos que você faça tudo sozinho implementando IXmlSerializable, nesse caso, você não ganhou muito usando XmlSerializer).

Marc Gravell
fonte
10
Não se esqueça do XStreamingElement, msdn.microsoft.com/en-us/library/… . :)
Todd White
1
Para o exemplo XmlWriter, é importante observar que você precisa fechar o gravador no final para que ele funcione corretamente - writer.Close () é necessário após o writer.WriteEndElement ().
Mark3
É verdade o que @Marko diz: É importante fechar o escritor corretamente. Também há outra maneira de fazer isso, em vez de chamar o writer.Close () diretamente. Você pode agrupar a chamada para Create () em uma instrução using como esta: using (XmlWriter writer = XmlWriter.Create (Console.Out)) {writer.WriteStartElement ("Foo"); etc} Há outro (um pouco mais avançado) exemplo de XmlWriter aqui: dotnetperls.com/xmlwriter
Morten
@ Morten Claro que se o XmlWriter implementa o IDisposable, usar a instrução é a melhor opção.
Marko
O bom e velho XMLDocument tem tudo isso. Direto, simples e claro se você estiver criando um documento XML.
FrenkyB 23/05/19
60

A melhor coisa que tentei é o LINQ to XSD (que é desconhecido para a maioria dos desenvolvedores). Você fornece a ele um esquema XSD e ele gera um modelo de objeto fortemente tipado e perfeitamente mapeado (baseado em LINQ to XML) para você em segundo plano, o que é realmente fácil de se trabalhar - e atualiza e valida seu modelo de objeto e XML em tempo real. Embora ainda seja "Preview", não encontrei nenhum bug com ele.

Se você tiver um esquema XSD parecido com este:

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

Então você pode simplesmente criar XML como este:

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

Ou simplesmente carregue um XML do arquivo como este:

RootElement rootElement = RootElement.Load(filePath);

Ou salve-o assim:

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

rootElement.Untyped também gera o elemento na forma de um XElement (de LINQ para XML).

user65199
fonte
parece que este código não está funcionando. quando estou disposto a fazer assim, não há aplicação de Save aplicadaRootElement
DanilGholtsman 31/03
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
fonte
10

XmlWriter é a maneira mais rápida de escrever um bom XML. XDocument, XMLDocument e alguns outros funcionam bem também, mas não são otimizados para escrever XML. Se você deseja escrever o XML o mais rápido possível, você definitivamente deve usar o XmlWriter.

Mikael Söderström
fonte
6
Ou seja, se você deseja que o computador grave o XML o mais rápido possível. Se você, desenvolvedor, deseja criar XML da maneira mais fácil e natural, o XmlWriter provavelmente não é a solução!
SJY
4

Eu acho que esse recurso deve ser suficiente para um carregamento / salvamento moderado de XML: Leitura / gravação de XML usando C # .

Minha tarefa era armazenar notação musical. Escolho o XML, porque acho que o .NET amadureceu o suficiente para permitir uma solução fácil para a tarefa. Eu tinha razão :)

Este é o meu protótipo de arquivo de música:

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

Isso pode ser resolvido facilmente:

Para Salvar no arquivo:

 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 carregar arquivo:

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

Para coisas simples, eu apenas uso as classes XmlDocument / XmlNode / XmlAttribute e o DOM XmlDocument encontrados no System.XML.

Ele gera o XML para mim, só preciso vincular alguns itens.

No entanto, em coisas maiores, eu uso serialização XML.

FlySwat
fonte
1

Para casos simples, eu também sugeriria olhar para o XmlOutput uma interface fluente para criar o Xml.

XmlOutput é ótimo para criação simples de XML, com código legível e de manutenção, enquanto gera um XML válido. O post original tem alguns ótimos exemplos.

Todd
fonte
-3

Como acima.

Eu uso stringbuilder.append ().

Muito simples, e você pode executar xmldocument.load (objeto strinbuilder como parâmetro).

Você provavelmente se encontrará usando string.concat dentro do parâmetro append, mas essa é uma abordagem muito direta.

GurdeepS
fonte
11
Exceto quando você se esquece de codificar algo corretamente e escreve Xml ilegal.
Robert Paulson
3
Essa resposta foi absolutamente violenta, mas com base nessa pergunta, examinei uma de minhas próprias implementações onde construí XML. Para o meu projeto em particular, constatei consistentemente que a criação via StringBuilder resultou em tempos de processamento 10% mais rápidos que o uso do XDocument / XmlWriter. Mas me sinto confortável com o XML, e isso é para o meu projeto em particular. (Para referência, tamanhos finais XML são cerca de 3,4 MB, com mais de 8000 linhas.)
James Skemp
2
Gostaria de saber se você mediu a troca entre desempenho de aplicativos (estamos falando de melhorias em milissegundos aqui?) E manutenção de aplicativos (seus engenheiros precisam se familiarizar com o código por uma hora antes de fazer alterações agora?)
Dan Esparza