Como você compararia dois documentos XML?

Como parte da class base para alguns testes de unidade extensiva, estou escrevendo uma function auxiliar que recursivamente compara os nós de um object XmlDocument para outro em C # (.net). Alguns requisitos deste:

  • O primeiro documento é a fonte , por exemplo, o que eu quero que o documento XML se pareça. Assim, o segundo é o que eu quero encontrar diferenças e não deve conter nós extras não no primeiro documento.
  • Deve lançar uma exceção quando muitas diferenças significativas são encontradas, e deve ser facilmente entendido por um olhar humano na descrição.
  • A ordem dos elementos filho é importante, os atributos podem estar em qualquer ordem.
  • Alguns atributos são ignoráveis; especificamente xsi:schemaLocation e xmlns:xsi , embora eu gostaria de poder passar quais são.
  • Os prefixos para namespaces devem corresponder aos atributos e elementos.
  • O espaço em branco entre os elementos é irrelevante.
  • Elementos terão elementos filho ou InnerText , mas não ambos.

Enquanto eu estou descartando algo: alguém já escreveu esse código e seria possível compartilhá-lo aqui?

De um lado, o que você chamaria de primeiro e segundo documentos? Eu tenho me referindo a eles como “source” e “target”, mas parece errado já que a fonte é o que eu quero que o alvo pareça, senão eu lancei uma exceção.

A Microsoft tem uma API XML diff que você pode usar

tente XMLUnit . Esta biblioteca está disponível para Java e .Net

Outra maneira de fazer isso seria –

  1. Obtenha o conteúdo de ambos os arquivos em duas sequências diferentes.
  2. Transforme as strings usando um XSLT (que copia tudo para duas novas strings). Isso garantirá que todos os espaços fora dos elementos sejam removidos. Isso resultará em duas novas seqüências.
  3. Agora, apenas compare as duas cordas entre si.

Isso não lhe dará a localização exata da diferença, mas se você quiser apenas saber se há alguma diferença, é fácil fazê-lo sem nenhuma biblioteca de terceiros.

Comparar documentos XML é complicado. Google para xmldiff (existe até uma solução da Microsoft) para algumas ferramentas. Eu resolvi isso de duas maneiras. Eu usei o XSLT para classificar elementos e atributos (porque algumas vezes eles apareceriam em uma ordem diferente, e eu não me importava com isso), filtrar os atributos que não queria comparar e usar o XML :: Diff ou XML :: SemanticDiff perl module, ou imprimiu bastante cada documento com cada elemento e atributo em uma linha separada, e usando o diff de linha de comando Unix nos resultados.

Este código não satisfaz todos os seus requisitos, mas é simples e estou usando para meus testes de unidade. A ordem do atributo não importa, mas a ordem dos elementos. O texto interno do elemento não é comparado. Eu também ignorei o caso ao comparar atributos, mas você pode facilmente remover isso.

 public bool XMLCompare(XElement primary, XElement secondary) { if (primary.HasAttributes) { if (primary.Attributes().Count() != secondary.Attributes().Count()) return false; foreach (XAttribute attr in primary.Attributes()) { if (secondary.Attribute(attr.Name.LocalName) == null) return false; if (attr.Value.ToLower() != secondary.Attribute(attr.Name.LocalName).Value.ToLower()) return false; } } if (primary.HasElements) { if (primary.Elements().Count() != secondary.Elements().Count()) return false; for (var i = 0; i <= primary.Elements().Count() - 1; i++) { if (XMLCompare(primary.Elements().Skip(i).Take(1).Single(), secondary.Elements().Skip(i).Take(1).Single()) == false) return false; } } return true; } 

Eu estou usando o ExamXML para comparar arquivos XML. Você pode experimentá-lo. Os autores, A7Soft, também fornecem API para comparar arquivos XML

https://github.com/CameronWills/FatAntelope Outra biblioteca alternativa para a API Microsoft XML Diff. Ele tem um algoritmo de diferenciação de XML para fazer uma comparação não ordenada de dois documentos XML e produzir uma correspondência ideal.

É uma porta C # do algoritmo X-Diff descrito aqui: http://pages.cs.wisc.edu/~yuanwang/xdiff.html

Disclaimer : Eu escrevi 🙂

Não relevante para o OP, uma vez que ele atualmente ignora a ordem dos filhos, mas se você quiser uma solução somente de código, você pode experimentar o XmlSpecificationCompare, que eu desenvolvi de forma um tanto equivocada .

Com base @Two Cents responder e usando este link XMLSorting eu criei meu próprio XmlComparer

Compare o programa XML

 private static bool compareXML(XmlNode node, XmlNode comparenode) { if (node.Value != comparenode.Value) return false; if (node.Attributes.Count>0) { foreach (XmlAttribute parentnodeattribute in node.Attributes) { string parentattributename = parentnodeattribute.Name; string parentattributevalue = parentnodeattribute.Value; if (parentattributevalue != comparenode.Attributes[parentattributename].Value) { return false; } } } if(node.HasChildNodes) { sortXML(comparenode); if (node.ChildNodes.Count != comparenode.ChildNodes.Count) return false; for(int i=0; i 

Ordenar programa XML

  private static void sortXML(XmlNode documentElement) { int i = 1; SortAttributes(documentElement.Attributes); SortElements(documentElement); foreach (XmlNode childNode in documentElement.ChildNodes) { sortXML(childNode); } } private static void SortElements(XmlNode rootNode) { for(int j = 0; j < rootNode.ChildNodes.Count; j++) { for (int i = 1; i < rootNode.ChildNodes.Count; i++) { if (String.Compare(rootNode.ChildNodes[i].Name, rootNode.ChildNodes[1 - 1].Name) < 0) { rootNode.InsertBefore(rootNode.ChildNodes[i], rootNode.ChildNodes[i - 1]); } } } // Console.WriteLine(j++); } private static void SortAttributes(XmlAttributeCollection attribCol) { if (attribCol == null) return; bool changed = true; while (changed) { changed = false; for (int i = 1; i < attribCol.Count; i++) { if (String.Compare(attribCol[i].Name, attribCol[i - 1].Name) < 0) { //Replace attribCol.InsertBefore(attribCol[i], attribCol[i - 1]); changed = true; } } } } 

Eu escrevi essa folha de comparação baseada no XSLT 1.0 que você compara o b.xml com o xml de input que gera diferenças de itens na input que não estão no b.xml.

https://github.com/sflynn1812/xslt-diff