none
Linq to XML - Diferenças entre os 2 arquivos xml RRS feed

  • Pergunta

  • Prezados, gostaria da ajuda de vocês.

     

    Tenho o seguinte problema.

    Tenho 2 arquivos XML com a mesma estrutura. (Exemplo abaixo)

     

     

     <data name="meuvalor1" xml:space="preserve">
      <value>valor 1</value>
     </data>
     <data name="meuvalor2" xml:space="preserve">
      <value>valor 2</value>
     </data>

     

    Preciso descobrir a diferença entre estes 2 arquivos.

    As diferenças que procuro são:

     

    1. Novas tags
    2. Tags com o valor diferente
    3. Tags com o valor igual (Eu sei isso não é diferença, porém para a regra que irei aplicar preciso desta comparação também)
    4. Tags removidas

    Quano comecei a fazer fiquei travado no linq.
    Como posso recuperar uma lista com as diferenças citadas acima usando linq?

    Vejam até onde cheguei:

          //Carrega 2 XML
          XDocument doc1 = XDocument.Load(txtResource1.Text);
          XDocument doc2 = XDocument.Load(txtResource1.Text);
    
          //Seleciona o 1 XML
          var list1 = from lv1 in doc1.Descendants("data")
                select new
                  {
                    Name = lv1.Attribute("name").Value
                    ,Value = lv1.Value
                  };
    
          //Seleciona o 2 XML
          var list2 = from lv2 in doc2.Descendants("data")
                select new
                {
                  Name = lv2.Attribute("name").Value
                  ,Value = lv2.Value
                };
    
                
          // E agora ??
          
    
          var NewTags = //Usando linq, lista tudo que tem em list1 e não existe em list2
          var TagsValueDiff = //Usando linq, lista tudo em que o valor das tags sejam diferentes (Atributo nome serve como identificador das tags)
          var TagsValueEquals = //Usando linq, lista tudo em que o valor das tags sejam iguais (Atributo nome serve como identificador das tags)
          var TagsRemoved = //Usando linq, lista tudo que tem em list2 e não existe em list1

    Agradeço muito a ajuda de vocês!!

     

    Obrigado.

     


    Abraços, Riderman | Analista de sistemas | MCTS SQL Server http://ridermansb.spaces.live.com/
    quinta-feira, 17 de junho de 2010 23:22

Respostas

  • Hi,

    Bom eu usei XElement que fica no assemble System.Xml.Linq ao envez do XDocument espero que nao seja um problema.

    XElement xml1 = XElement.Parse("<DS>" + txtResource1.Tex + "</DS>");
    XElement xml2 = XElement.Parse("<DS>" + txtResource2.Tex + "</DS>");
    
    var ntx1 =
      from x1 in xml1.Elements()
      select x1.Attribute("name").Value;
    
    var newTags2 =
      from x2 in xml2.Elements()
      where !ntx1.Contains(x2.Attribute("name").Value)
      select x2;
    
    var tagValueDiff =
      from x1 in xml1.Elements()
      join x2 in xml2.Elements() on x1.Attribute("name").Value equals x2.Attribute("name").Value
      where x1.Element("value").Value != x2.Element("value").Value
      select new { x1, x2 };
    
    var tagValueEquals =
      from x1 in xml1.Elements()
      join x2 in xml2.Elements() on x1.Attribute("name").Value equals x2.Attribute("name").Value
      where x1.Element("value").Value == x2.Element("value").Value
      select new { x1, x2 };
    
    var ntx2 =
      from x2 in xml2.Elements()
      select x2.Attribute("name").Value;
    
    var newTags1 =
      from x1 in xml1.Elements()
      where !ntx2.Contains(x1.Attribute("name").Value)
      select x1;
    
    //Usando linq, lista tudo que tem em list1 e não existe em list2
    var NewTags = newTags2;
    //Usando linq, lista tudo em que o valor das tags sejam diferentes (Atributo nome serve como identificador das tags)
    var TagsValueDiff = tagValueDiff;
    //Usando linq, lista tudo em que o valor das tags sejam iguais (Atributo nome serve como identificador das tags)
    var TagsValueEquals = tagValueEquals;
    //Usando linq, lista tudo que tem em list2 e não existe em list1
    var TagsRemoved = newTags1;

    Att,


    Adriel Codeco Silva Microsoft Partner http://adrielcodeco.wordpress.com www.uppercase.com.br adrielcodeco@hotmail.com
    sexta-feira, 18 de junho de 2010 01:33
    Moderador
  • Prezado,

    Veja se isto te ajuda em algo:

    http://deepumi.wordpress.com/2010/03/02/compare-xml-files-using-csharp-linq/


    André Alves de Lima
    Visite o meu site: http://andrealveslima.spaces.live.com
    Me siga no Twitter: @andrealveslima
    sexta-feira, 18 de junho de 2010 00:49
    Moderador

Todas as Respostas

  • Prezado,

    Veja se isto te ajuda em algo:

    http://deepumi.wordpress.com/2010/03/02/compare-xml-files-using-csharp-linq/


    André Alves de Lima
    Visite o meu site: http://andrealveslima.spaces.live.com
    Me siga no Twitter: @andrealveslima
    sexta-feira, 18 de junho de 2010 00:49
    Moderador
  • Hi,

    Bom eu usei XElement que fica no assemble System.Xml.Linq ao envez do XDocument espero que nao seja um problema.

    XElement xml1 = XElement.Parse("<DS>" + txtResource1.Tex + "</DS>");
    XElement xml2 = XElement.Parse("<DS>" + txtResource2.Tex + "</DS>");
    
    var ntx1 =
      from x1 in xml1.Elements()
      select x1.Attribute("name").Value;
    
    var newTags2 =
      from x2 in xml2.Elements()
      where !ntx1.Contains(x2.Attribute("name").Value)
      select x2;
    
    var tagValueDiff =
      from x1 in xml1.Elements()
      join x2 in xml2.Elements() on x1.Attribute("name").Value equals x2.Attribute("name").Value
      where x1.Element("value").Value != x2.Element("value").Value
      select new { x1, x2 };
    
    var tagValueEquals =
      from x1 in xml1.Elements()
      join x2 in xml2.Elements() on x1.Attribute("name").Value equals x2.Attribute("name").Value
      where x1.Element("value").Value == x2.Element("value").Value
      select new { x1, x2 };
    
    var ntx2 =
      from x2 in xml2.Elements()
      select x2.Attribute("name").Value;
    
    var newTags1 =
      from x1 in xml1.Elements()
      where !ntx2.Contains(x1.Attribute("name").Value)
      select x1;
    
    //Usando linq, lista tudo que tem em list1 e não existe em list2
    var NewTags = newTags2;
    //Usando linq, lista tudo em que o valor das tags sejam diferentes (Atributo nome serve como identificador das tags)
    var TagsValueDiff = tagValueDiff;
    //Usando linq, lista tudo em que o valor das tags sejam iguais (Atributo nome serve como identificador das tags)
    var TagsValueEquals = tagValueEquals;
    //Usando linq, lista tudo que tem em list2 e não existe em list1
    var TagsRemoved = newTags1;

    Att,


    Adriel Codeco Silva Microsoft Partner http://adrielcodeco.wordpress.com www.uppercase.com.br adrielcodeco@hotmail.com
    sexta-feira, 18 de junho de 2010 01:33
    Moderador
  • André eu não tenho uma classe, por isso não posso implementar a interface IEqualityComparer.

    O objeto é anonymous object, por isso não tenho acesso ao mesmo.


    Abraços, Riderman | Analista de sistemas | MCTS SQL Server http://ridermansb.spaces.live.com/
    sexta-feira, 18 de junho de 2010 02:53
  • Olá Adriel, testei seu exemplo porém não deu muito certo.

    Criei 2 arquivos XML, populei com 2 registros no primeiro e 3 no segundo, porém ele não me retornou as novas tags.

    Os outros não testei.


    Abraços, Riderman | Analista de sistemas | MCTS SQL Server http://ridermansb.spaces.live.com/
    sexta-feira, 18 de junho de 2010 02:55
  • Hi,

    Funciona sim man, e que eu esqueci de destrocar o newtag2 pelo newtag1 eles estao trocados, mas confere denovo.

    string _xml1 =
      "   <data name=\"meuvalor1\" xml:space=\"preserve\">" +
      "     <value>valor 1</value>" +
      "   </data>" +
      "   <data name=\"meuvalor3\" xml:space=\"preserve\">" +
      "     <value>valor 3</value>" +
      "   </data>" +
      "   <data name=\"meuvalor4\" xml:space=\"preserve\">" +
      "     <value>valor 41</value>" +
      "   </data>";
    string _xml2 =
      "   <data name=\"meuvalor1\" xml:space=\"preserve\">" +
      "     <value>valor 1</value>" +
      "   </data>" +
      "   <data name=\"meuvalor2\" xml:space=\"preserve\">" +
      "     <value>valor 2</value>" +
      "   </data>" +
      "   <data name=\"meuvalor4\" xml:space=\"preserve\">" +
      "     <value>valor 42</value>" +
      "   </data>";
    
    XElement xml1 = XElement.Parse("<DS>" + _xml1 + "</DS>");
    XElement xml2 = XElement.Parse("<DS>" + _xml2 + "</DS>");
    
    var ntx1 =
     from x1 in xml1.Elements()
     select x1.Attribute("name").Value;
    
    var newTags2 =
     from x2 in xml2.Elements()
     where !ntx1.Contains(x2.Attribute("name").Value)
     select x2;
    
    var tagValueDiff =
     from x1 in xml1.Elements()
     join x2 in xml2.Elements() on x1.Attribute("name").Value equals x2.Attribute("name").Value
     where x1.Element("value").Value != x2.Element("value").Value
     select new { x1, x2 };
    
    var tagValueEquals =
     from x1 in xml1.Elements()
     join x2 in xml2.Elements() on x1.Attribute("name").Value equals x2.Attribute("name").Value
     where x1.Element("value").Value == x2.Element("value").Value
     select new { x1, x2 };
    
    var ntx2 =
     from x2 in xml2.Elements()
     select x2.Attribute("name").Value;
    
    var newTags1 =
     from x1 in xml1.Elements()
     where !ntx2.Contains(x1.Attribute("name").Value)
     select x1;
    
    //Usando linq, lista tudo que tem em list1 e não existe em list2
    var NewTags = newTags1.ToList();
    //Usando linq, lista tudo em que o valor das tags sejam diferentes (Atributo nome serve como identificador das tags)
    var TagsValueDiff = tagValueDiff.ToList();
    //Usando linq, lista tudo em que o valor das tags sejam iguais (Atributo nome serve como identificador das tags)
    var TagsValueEquals = tagValueEquals.ToList();
    //Usando linq, lista tudo que tem em list2 e não existe em list1
    var TagsRemoved = newTags2.ToList();

    Voce so tem que tratar o resultado do jeito que precisa. Esse foi o teste que fiz aqui e funcionou.

    Att,


    Adriel Codeco Silva Microsoft Partner http://adrielcodeco.wordpress.com www.uppercase.com.br adrielcodeco@hotmail.com
    sexta-feira, 18 de junho de 2010 12:53
    Moderador
  • Não poderia fazer algo assim? óbvio que estou retornar um list de String para exemplificar meu raciocinio

     

    public List<string> Comparar(XElement xml1, XElement xml2)

            {

                List<string> diferentes = new List<string>();

                foreach (var item in xml1.Elements())

                {

                    string Valor1 = item.Value;

                    string Valor2 = xml2.Element(item.Name).Value;

     

                    if (Valor1 != Valor2)

                    {

                        diferentes.Add(Valor1 + ":" + Valor2);

                    }

                }

     

                return diferentes;

     

            }

     


    Minato alexandre.minato@hotmail.com - http://www.alexandreminato.com.br
    segunda-feira, 21 de junho de 2010 12:45
  • Pessoal, obrigado a todos pela resposta.

     

    Adriel, sua resposta estava correta, o erro foi meu.

     

    Se vocês repararem no código fonte estou carregando o mesmo XML 2 vezes.

     

      //Carrega 2 XML
       XDocument doc1 = XDocument.Load(txtResource1.Text);
       XDocument doc2 = XDocument.Load(txtResource1.Text);

    Já corrigi o problema e funcionou!

     

    Obrigado a todos!


    Abraços, Riderman | Analista de sistemas | MCTS SQL Server http://ridermansb.spaces.live.com/
    quarta-feira, 23 de junho de 2010 23:05