t

Comentários recentes

Criando e manipulando XML com Linq to XML

Postado por Daniel Fonseca Castro - Monday, August 18, 2008 5:23 PM

Introdução

Criar e manipular XML utilizando Linq to XML ficou muito mais fácil, existem muitas possibilidades para criar e manipular XML utilizando o .NET Framework. XPath: é uma das opções mais para tirar o máximo proveito do XPath você precisa de bons conhecimentos de expressões regulares . XmlDocument: é uma implementação da Microsoft para criação de documentos XML , conforme as especificações W3C DOM. DataSet e DataTable: eles não foram criados para manipular XML , mais muitos desenvolvedores utilizam os métodos WriteXml e ReadXml para criar e ler arquivos XML, funciona perfeitamente mais o objetivo do DataSet e DataTable é outro.

O Linq to XML, substitui todas as opções disponíveis como a vantagem de ser extremante simples, ao final desse artigo você percebera que com apenas um objeto você consegue criar e manipular arquivos XML.

Recursos utilizados

-Visual Studio 2008 Express Edition SP1.

Criando projeto

Para demonstra com utilizar o Linq to XML vamos criar uma aplicação do Tipo Console Application. Clique em File,selecione New Project e Console Application ,na caixa nome altere o valor para LinqToXMLExemplo.

Criando XML

Na definição da classe Program adiciona o campo arquivo conforme código abaixo.

static string arquivo = "C:\\documento.xml";
Dim arquivo As String = "C:\\documento.xml"

O namespace System.Xml.Linq contém todos os objetos necessários para cria e manipular XML ,para criar um arquivo XML vamos utilizar a classe XElement .Todos com atributos e elementos serão criados com os métodos SetAttributeValue e SetElementValue, para salvar o arquivo a classe disponibiliza o método Save.

Conforme o código abaixo adicione o método CriaXML a definição da classe Program e chame-o do método Main.

static void CriaXML()
{
    XElement documentoXml = new XElement("Clientes");
    XElement element = null;

    for (int i = 1; i <= 5; i++)
    {
        element = new XElement("Cliente", new XComment("Atributos do cliente " + i));

        //Atributos
        element.SetAttributeValue("Nome", String.Format("Nome {0}", i));
        element.SetAttributeValue("Endereco", String.Format("Endereço {0}", i));

        //Elementos
        element.SetElementValue("RG", String.Format("RG {0}", i));
        element.SetElementValue("CPF", String.Format("CPF {0}", i));

        //Adiciona elemento ao elemento root
        documentoXml.Add(element);
    }

    documentoXml.Save(arquivo);

    Console.WriteLine(documentoXml);
}
Sub CriaXML()
    Dim documentoXml As New XElement("Clientes")
    Dim element As XElement = Nothing

    For I As Integer = 1 To 5
        element = New XElement("Cliente", New XComment("Atributos do cliente " + I.ToString()))

        'Atributos
        element.SetAttributeValue("Nome", String.Format("Nome {0}", I))
        element.SetAttributeValue("Endereco", String.Format("Endereço {0}", I))

        'Elementos
        element.SetElementValue("RG", String.Format("RG {0}", I))
        element.SetElementValue("CPF", String.Format("CPF {0}", I))

        'Adiciona elemento ao elemento root
        documentoXml.Add(element)
    Next

    documentoXml.Save(arquivo)

    Console.WriteLine(documentoXml)
End Sub

Resultado da execução do método CriaXML.



  
    
    RG 1
    CPF 1
  
  
    
    RG 2
    CPF 2
  
  
    
    RG 3
    CPF 3
  
  
    
    RG 4
    CPF 4
  
  
    
    RG 5
    CPF 5
  

Carregar arquivo

Para carregar e selecionar valores utilizando Linq to XML podemos utilizar a classe XElement. Método Load: carregar conteúdo XML de um arquivo ou da memórias é a responsabilidade desse método, em uma de suas sobrecargas podemos passar o caminho do arquivo XML , as outras sobrecargas recebe como parâmetros um objeto TextReader ou XmlReader.Você também pode definir opções à partir do enum LoadOptions.

O LoadOption possui quatro opções . None : todas as linhas desnecessárias,linhas em branco e linhas de informações, do arquivo XML não serão carregadas. PreserveWhitespace: essa opção define que todas as linhas em branco do arquivo XML serão preservadas. SetBaseUri : essa opção define o preenchimento da propriedade BaseUri. SetLineInfo: essa opção habilita o preenchimento da das informações de linha, essa informações pode ser recuperadas através da interface IXmlLineInfo.

Conforme código abaixo adicione o método CarregaSelecionaXml na definição da classe Program e chame-o do método Main.

static void CarregaSelecionaXml()
{
    XElement xml = XElement.Load(arquivo, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);

    //Mostra o caminho base.
    Console.WriteLine("Caminho : {0}", xml.BaseUri);

    //Mostra informações de linha 
    IXmlLineInfo lineInfo = xml as IXmlLineInfo;
    Console.WriteLine("LineNumber : {0} e LinePosition: {1}", lineInfo.LineNumber, lineInfo.LinePosition);

    //Carrega todos os elementos dentro do elemento root
    IEnumerable enumerable = xml.Elements();

    //Mostra todos os elementos dentro do elemento root
    foreach (var item in enumerable)
        Console.WriteLine(item);

    //Mostra todos os atributos nome do elento Cliente
    foreach (var item in enumerable.Attributes("Nome"))
        Console.WriteLine(item);

    //Mostra todos os elementos CPF dentro do elemento Cliente
    foreach (var item in enumerable.Elements("CPF"))
        Console.WriteLine(item);
}
Sub CarregaSelecionaXml()
    Dim xml As XElement = XElement.Load(arquivo, LoadOptions.SetBaseUri Or LoadOptions.SetLineInfo)

    'Mostra o caminho base.
    Console.WriteLine("Caminho : {0}", xml.BaseUri)

    'Mostra informações de linha 
    Dim lineInfo As IXmlLineInfo = xml

    Console.WriteLine("LineNumber : {0} e LinePosition: {1}", lineInfo.LineNumber, lineInfo.LinePosition)

    'Carrega todos os elementos dentro do elemento root
    Dim Enumerable As IEnumerable(Of XElement) = xml.Elements()

    'Mostra todos os elementos dentro do elemento root
    For Each item In Enumerable
        Console.WriteLine(item)
    Next

    'Mostra todos os atributos nome do elento Cliente
    For Each item In Enumerable.Attributes("Nome")
        Console.WriteLine(item)
    Next

    'Mostra todos os elementos CPF dentro do elemento Cliente
    For Each item In Enumerable.Elements("CPF")
        Console.WriteLine(item)
    Next
End Sub

Alterando valores

Para isso utilizamos todo o poder do Linq para selecionar o atributo ou elemento que desejamos alterar.

Conforme o código abaixo adicione o método AlterandoValores na definição da classe Program e chame-o do método Main.

static void AlterandoValores()
{
    XElement xml = XElement.Load(arquivo, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
    IEnumerable<XElement> elements = xml.Elements();

    //Seleciona e altera o elemento CPF aonde o valor seja igual a "CPF 1"
    foreach (var item in elements.Elements("CPF").Where(e => e.Value == "CPF 1"))
        item.Value = "123456789";

    //Seleciona e altera o atributo Nome aonde o valor seja igual a "Nome 1"
    foreach (var item in elements.Attributes("Nome").Where(e => e.Value == "Nome 1"))
        item.Value = "Nome Alterado";

    //Salva Alterações
    xml.Save(arquivo);
}
Sub AlterandoValores()
    Dim xml As XElement = XElement.Load(arquivo, LoadOptions.SetBaseUri Or LoadOptions.SetLineInfo)

    Dim elements As IEnumerable(Of XElement) = xml.Elements()

    'Seleciona e altera o elemento CPF aonde o valor seja igual a "CPF 1"
    For Each item In elements.Elements("CPF").Where(Function(e) e.Value = "CPF 1")
        item.Value = "123456789"
    Next

    'Seleciona e altera o atributo Nome aonde o valor seja igual a "Nome 1"
    For Each item In elements.Attributes("Nome").Where(Function(e) e.Value = "Nome 1")
        item.Value = "Nome Alterado"
    Next

    'Salva Alterações
    xml.Save(arquivo)
End Sub

Excluindo Valores

O código abaixo demonstra como excluir um elemento do arquivo XML, esse exemplo retira o elemento cliente aonde o atributo nome seja igual a "Nome 2", e para isso vamos utilizar mais uma vez o poder do Linq.

Conforme o código abaixo adicione o método ExcluindoValores na definição da classe Program e chame-o do método Main.

static void ExcluindoValores()
{
    XElement xml = XElement.Load(arquivo, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
    IEnumerable<XElement> elements = xml.Elements();

    //Exclui elemento Cliente aonde o Atributo Nome seja igual a "Nome 2"
    elements.AncestorsAndSelf("Cliente").Where(e => e.Attribute("Nome").Value == "Nome 2").Remove();

    //Salva Alterações
    xml.Save(arquivo);
}
Sub ExcluindoValores()
    Dim xml As XElement = XElement.Load(arquivo, LoadOptions.SetBaseUri Or LoadOptions.SetLineInfo)

    Dim elements As IEnumerable(Of XElement) = xml.Elements()

    'Exclui elemento Cliente aonde o Atributo Nome seja igual a "Nome 2"
    elements.AncestorsAndSelf("Cliente").Where(Function(e) e.Attribute("Nome").Value = "Nome 2").Remove()

    'Salva Alterações
    xml.Save(arquivo)
End Sub

Conclusão

Com esse simples exemplo da para se ter idéia do que o Linq to XML e capaz, a criação de manipulação de arquivos XML ficou muito mais fácil, ficou claro que o objeto XElement possui todas as funcionalidades necessárias para manipulação de arquivos XML, claro o Linq to XML não se define a um único objeto mais ele com certeza da conta do recado.

Referências

http://msdn.microsoft.com/en-us/library/bb308960.aspx

Código Fonte

Daniel Fonseca Castro

Currently rated 4.9 by 8 people

  • Currently 4.875/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Linq

Related posts

  • Daniel
    Daniel
    28 Oct 2008 12:03 PM
    Show de bola... me ajudou muito...

    Mas como fazer para inserir novos dados em um arquivo xml que já existe e que contem registros?

    Obrigado pelo artigo.

    Daniel
  • Daniel Fonseca Castro
    Daniel Fonseca Castro
    28 Oct 2008 12:04 PM
    Olá Daniel

    Você pode utilizar os métodos SetAttributeValue e SetElementValue, como no exemplo do método CriaXML

    Daniel Fonseca Castro
  • Marcel Inowe
    Marcel Inowe
    28 Oct 2008 12:05 PM
    Parabéns Daniel, me ajudou muito seu exemplo.
  • Caracas meu
    Caracas meu
    04 Nov 2008 10:27 PM
    Muito bom este artigo, tiro o chapéu, como ele fica moleza entender LINQ + XML

    Vlw mesmo
  • Gigio
    Gigio
    26 May 2009 2:38 PM
    cara sei que ja faz um tempo desde que criou este artigo...mas muito obrigado, muito bom meesmo linq é coisa bunita de deus ^^
  • Eduardo Melo
    Eduardo Melo
    05 Jul 2009 3:12 PM
    Boa tarde Dan, cara se voce puder alterar o exemplo, pois para um leigo acredito que ele não saberia que o "e" referenciado dentro do where da seção de atualização do xml e na verdade o "item" instanciado dentro do proprio ForEach.

    Um grande abraço.
  • Daniel Fonseca Castro
    Daniel Fonseca Castro
    05 Jul 2009 6:58 PM
    Olá Eduardo,

    Nesse exemplo eu utilizei Lambda Expressions, veja referências
    msdn.microsoft.com/pt-br/library/bb397687.aspx
    msdn.microsoft.com/en-us/library/bb397687.aspx

    A outra opção para construção desse exemplo seria construir as consultas sem a ajuda do método de extensão Where,utilizando linq direto, por exemplo

    static void AlterandoValores()
    {
    XElement xml = XElement.Load(arquivo, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
    IEnumerable<XElement> elements = xml.Elements();

    //Seleciona e altera o elemento CPF aonde o valor seja igual a "CPF 1"
    var cpf = (from x in elements.Elements("CPF")
    where x.Value == "CPF 1"
    select x).FirstOrDefault();
    cpf.Value = "123456789";

    //Seleciona e altera o atributo Nome aonde o valor seja igual a "Nome 1"
    var nome = (from x in elements.Attributes("Nome")
    where x.Value == "Nome 1"
    select x).FirstOrDefault();

    nome.Value = "Nome Alterado";

    //Salva Alterações
    xml.Save(arquivo);
    }

    Não sei se fica mais fácil , mais esta ai

    Abraços,
    Daniel Fonseca Castro
  • Eduardo Britto
    Eduardo Britto
    24 Jul 2009 8:35 AM
    Olá Daniel,
    Parabéns pelo excelente artigo. Me ajudou muito. Ainda estou me atualizando e é muito difícil achar artigos em português com essa qualidade.
    []s
  • Wellington Dala
    Wellington Dala
    29 Jul 2009 10:46 AM
    Ola, muito legal esse post, parabéns.

    Se alguem souber, poderia me mandar um codigo de como acrescentar elementos a um documento xml.

    pelo que entendi, nesse post so tem como aleterar os campos ja existentes, mas nao como acrescentar novos.

    valeu.
  • Daniel Fonseca Castro
    Daniel Fonseca Castro
    29 Jul 2009 7:15 PM
    Olá Wellington,

    vou usar com exemplo o arquivo xml gerado nesse post!

    XElement xml = XElement.Load("arquivo.xml", LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);

    //Adiciona elemento dentro do root
    xml.SetElementValue("DentroRoot", "valor");

    foreach (var item in xml.Elements())
    {
    //Adiciona elemento
    item.SetElementValue("DentroDosElementosCliente", "Valor");

    //Adiciona atributo
    item.SetAttributeValue("NovoAtributoParaTodosElementosCliente", "Valor");
    }
    ...

    Resultado

    <Clientes>
    <Cliente Nome="Nome 1" Endereco="Endereço 1" NovoAtributoParaTodosElementosCliente="Valor">
    <!--Atributos do cliente 1-->
    <RG>RG 1</RG>
    <CPF>CPF 1</CPF>
    <DentroDosElementosCliente>Valor</DentroDosElementosCliente>
    </Cliente>
    ....
    <DentroRoot NovoAtributoParaTodosElementosCliente="Valor">valor<DentroDosElementosCliente>Valor</DentroDosElementosCliente></DentroRoot>
    </Clientes>

    Abraços,
    Daniel Fonseca Castro
  • Pedro Junior
    Pedro Junior
    09 Oct 2009 11:38 AM
    Poderia mandar esse codigo fonte em c#...
  • Daniel Fonseca Castro
    Daniel Fonseca Castro
    09 Oct 2009 6:10 PM
    Olá Pedro,

    O fonte esta disponível neste link
    http://tinyurl.com/ylxuhlm

    Abraços,
    Daniel Fonseca Castro
  • Wellington Patroni de Melo
    Wellington Patroni de Melo
    20 Apr 2010 2:26 PM
    Daniel meus parabens pela qualidade deste artigo foi muito util.

    Parabens.
  • Wellington Patroni de Melo
    Wellington Patroni de Melo
    21 Apr 2010 8:07 PM
    Ola Daniel,

    como posso pesquisar um codigo de um XML e eu consiga pegar todos os elementos e atributos de um root

    tem algum exemplo de como fazer isso?

    Obrigado

    Wellington
  • Daniel Fonseca Castro
    Daniel Fonseca Castro
    21 Apr 2010 9:28 PM
    Olá Wellington,

    Passa um exemplo do XML e os elementos ou atributos que você quer pegar,assim fica mais fácil enxergar a situação!

    Abraços,
    Daniel Fonseca Castro
  • Wellington Patroni de Melo
    Wellington Patroni de Melo
    22 Apr 2010 10:33 PM
    Olá Daniel

    Esse e o XML e a função de Busca, mas não consigo retornar os valores....


    <?xml version="1.0" encoding="utf-8"?>
    <Produto.xml>
    <Produto Codigo="0000000000001" Descricao="Descricao 1">
    <!--Atributos do Produto1-->
    <Aliquota>NN</Aliquota>
    <Preco>1,00</Preco>
    </Produto>
    <Produto Codigo="0000000000002" Descricao="Descricao 2">
    <!--Atributos do Produto2-->
    <Aliquota>NN</Aliquota>
    <Preco>2,00</Preco>
    </Produto>
    <Produto Codigo="0000000000003" Descricao="Descricao 3">
    <!--Atributos do Produto3-->
    <Aliquota>NN</Aliquota>
    <Preco>3,00</Preco>
    </Produto>
    </Produto.xml>


    Public Sub BuscaProdutoXML(ByVal pCodigo As String, ByRef pDescricao As String, ByRef pAliquota As String, ByRef pPreco As String)

    Dim ArquivoXML As String = CaminhoBaseXML & "\Produto.xml"

    Dim xml As XElement = XElement.Load(ArquivoXML, LoadOptions.SetBaseUri Or LoadOptions.SetLineInfo)
    Dim elements As IEnumerable(Of XElement) = xml.Elements()

    Dim Produtos = From p In xml.Elements("Produto") Where p.Element("Codigo") = "'" & pCodigo & "'" Select p

    For Each Item In Produtos
    pDescricao = Item.Element("Descricao").ToString
    pAliquota = Item.Element("Aliquota").ToString
    pPreco = Item.Element("Preco").ToString
    Next

    End Sub


    desde ja Obrigado pela ajuda...

    []'s

    Wellington
  • Daniel Fonseca Castro
    Daniel Fonseca Castro
    24 Apr 2010 7:44 AM
    Olá Wellington,

    Você pode fazer assim.

    Public Sub BuscaProdutoXML(ByVal pCodigo As String, ByRef pDescricao As String, ByRef pAliquota As String, ByRef pPreco As String)

    Dim ArquivoXML As String = CaminhoBaseXML & "\Produto.xml"

    Dim xml As XElement = XElement.Load(ArquivoXML, LoadOptions.SetBaseUri Or LoadOptions.SetLineInfo)
    Dim elements As IEnumerable(Of XElement) = xml.Elements()

    For Each Item In elements
    If Item.Attributes("Codigo").Where(Function(x) x.Value = pCodigo).Count() > 0 Then
    pDescricao = Item.Attributes("Descricao").First().Value
    pAliquota = Item.Elements("Aliquota").First().Value
    pPreco = Item.Elements("Preco").First().Value
    Exit For
    End If
    Next

    End Sub

    Abraços,
    Daniel Fonseca Castro
  • Germano
    Germano
    15 Jul 2010 9:46 AM
    Olá Daniel. Muito bom seu artigo.
    Tenho o seguinte XML e não estou conseguindo adaptar sua rotina para ler os valores de cada nó. Pode me ajudar? Obrigado. (o xml foi gerado a partir de uma exportação de tabela de banco de dados). Fazendo um debug consigo identificar onde estão os valores, mas não consegui adaptar a forma para ler os atributos.

    <?xml version='1.0' encoding='UTF-8' ?>
    <RESULTS>
    <ROW>
    <COLUMN NAME="CODIGO_PREDIO"><![CDATA[996]]></COLUMN>
    <COLUMN NAME="DESCRICAO_PREDIO"><![CDATA[PREDIO 02TA]]></COLUMN>
    </ROW>
    <ROW>
    <COLUMN NAME="CODIGO_PREDIO"><![CDATA[997]]></COLUMN>
    <COLUMN NAME="DESCRICAO_PREDIO"><![CDATA[SETORES EXTINTOS]]></COLUMN>
    </ROW>
    <ROW>
    <COLUMN NAME="CODIGO_PREDIO"><![CDATA[998]]></COLUMN>
    <COLUMN NAME="DESCRICAO_PREDIO"><![CDATA[TJRS]]></COLUMN>
    </ROW>
    <ROW>
    <COLUMN NAME="CODIGO_PREDIO"><![CDATA[999]]></COLUMN>
    <COLUMN NAME="DESCRICAO_PREDIO"><![CDATA[PJRS]]></COLUMN>
    </ROW>
    </RESULTS>
  • Germano
    Germano
    15 Jul 2010 1:37 PM
    Olá Daniel. Já consegui resolver meu problema.
    para cada ROW eu pego o FirstNode e o LastNode e o valor correspondente.

    CType(item.LastNode, XElement).Value

    Abraços.

Add comment


 

  Country flag