Confronto XML a quattro vie in C #

5

Ho 4 file XML: A, B, C e D. Voglio sapere se la differenza tra A e B è uguale alla differenza tra C e D.

I file XML sono serializzazioni dello stesso oggetto .NET; una delle differenze principali sarà in un particolare elenco che descrive le funzionalità disponibili su un particolare prodotto. (Una descrizione della funzione è di per sé un altro oggetto).

Tutti e quattro hanno strutture molto simili, ma ci possono essere valori presenti in uno che non sono presenti in un altro, e alcuni valori possono essere cambiati. Ad esempio, se consideriamo il documento A :

<xmldoc>
   <a></a>
   <c></c>
   <d></d>
<xmldoc>

Documento B :

<xmldoc>
   <a></a>
   <b></b> -- Added 
   <c></c> -- C and D are still ordered in the same way (except for the addition of <b>
   <d></d>
   <e></e> -- Also added, but it doesn't affect the sort of the other ones
<xmldoc>

Ora supponiamo di avere i seguenti documenti. Il documento C è esattamente identico al documento A :

<xmldoc>
   <a></a>
   <c></c>
   <d></d>
<xmldoc>

Il documento D è identico al documento B .

Poiché la differenza tra C e D è esattamente uguale alla differenza tra A e B , questo dovrebbe passare. Tuttavia, supponiamo di avere invece il documento D come segue:

<xmldoc>
   <a></a>
   <b></b> 
   <f></f> <!-- Added -->
   <c></c>
   <d></d>
   <e></e>
   <f></f>
<xmldoc>

La differenza tra C e D non è più uguale alla differenza tra A e B .

Sono abbastanza sicuro che non avremo un caso in cui il documento A si presenta come:

<xmldoc>
   <c></c>
   <a></a> -- This is the same as the original document A except that this was reordered - this shouldn't happen
   <d></d>
<xmldoc>

Il mio primo pensiero è stato quello di utilizzare la libreria XML Diff Patch di Microsoft, che confronta due file e genera un DiffGram, che è un documento XML che descrive la differenza tra i due file confrontati. Il mio pensiero è che potrei confrontare A a B per ottenere DiffGram X e C a D per ottenere DiffGram Y, e quindi fare un terzo confronto XML tra X e Y.

L'idea suona bene sulla carta; sfortunatamente non si sta rivelando così semplice. La differenza tra A e B è molto simile alla differenza tra C e D, ma X e Y non assomigliano l'un l'altro.

Il problema è che dà a DiffGram il seguente:

<xd:node match="4">
           <xd:node match="2">
              <xd:node match="1">
                 <xd:remove match="1-3" />
              </xd:node>
           </xd:node>

           <xd:node match="1">
              <xd:node match="1">
                 <xd:remove match="1-3" />
              </xd:node>
           </xd:node>
        </xd:node>

Questo ha due problemi: in primo luogo, è estremamente criptico - preferirei che fosse più leggibile dall'uomo, ma non è la fine del mondo se non è così (dal mio lo scopo principale è programmatico qui). In secondo luogo (e molto più criticamente), sembra che sia strettamente correlato agli specifici file XML che sono in quel particolare confronto.

Originariamente pubblicato sul Software Recommendation Stack Exchange chiedendo consigli per una libreria .NET (preferibilmente disponibile come pacchetto NuGet) che sarebbe adatta a questo scopo ma non ho avuto molta fortuna ad ottenere una raccomandazione. (Full disclosure: Non ho ancora cancellato quella domanda ma intendo farlo a breve). Se esiste una libreria di questo tipo, non sono stato in grado di trovarla (molti di essi sembrano non essere progettati per lo scopo in cui voglio usarli e / o non sono scritti per il framework .NET), ma se qualcuno è a conoscenza di una tale libreria che sarebbe sicuramente una soluzione accettabile (in effetti, preferirei strongmente che dovessi implementarla da solo).

Qualcuno ha fatto qualcosa di simile (creando la propria soluzione, usando la libreria Microsoft XML Diff o usando un'altra libreria di terze parti)? Se sì, cosa hai fatto?

Spero che non sia una domanda troppo ampia (se è così fammelo sapere e modifico), ma quale sarebbe un buon approccio se finissi per scrivere da solo?

    
posta EJoshuaS 10.11.2016 - 18:04
fonte

3 risposte

3

My thought is that I could compare A to B to get DiffGram X and C to D to get DiffGram Y, and then do a third XML comparison between X and Y.

Sembra essere un buon inizio. Immagino che ciò che manca qui sia qualcosa come un programma o uno script xslt per trasformare "DiffGram X" in una rappresentazione leggibile X '. Quindi puoi applicare la stessa trasformazione a Diffgram Y, portando a una Y leggibile. Confrontando X 'e Y' si ottiene un DiffGram Z finale, che potrebbe essere trasformato in una Z leggibile.

Il modo in cui questo script o programma verrà visualizzato dipende probabilmente dal tipo di ipotesi che si possono fare sulla struttura dei file di input. Sono davvero costituiti da alberi XML nidificati arbitrari? Hai bisogno di confrontare attributi, denominare gli elementi di differenze spaziali e anche i testi degli elementi? Sarei stupito se non si potesse usare quella conoscenza per semplificare i DiffGram.

    
risposta data 10.11.2016 - 22:10
fonte
2

Solo una risposta generica. Esiste una raccomandazione denominata Set di informazioni XML:

link

Direi che il modo più accurato per calcolare la differenza (o "delta") tra due documenti XML, e quindi confrontare tali differenze da soli, sarà dopo aver usato l'API / componente (out of the box, aumentato o personalizzato) supporta i costrutti definiti in quella raccomandazione nel modo più fedele.

'HTH,

    
risposta data 10.11.2016 - 22:58
fonte
1

La rappresentazione DiffGram delle modifiche non funziona bene per questa situazione. Va bene per l'applicazione di patch ai file, ma non per questo tipo di applicazione. L'utilizzo di DeltaXML offre una rappresentazione più utile delle differenze tra i tuoi documenti A e B:

<xmldoc deltaxml:deltaV2="A!=B" deltaxml:version="2.0" deltaxml:content-type="full-context" xmlns:deltaxml="http://www.deltaxml.com/ns/well-formed-delta-v1">
 <a deltaxml:deltaV2="A=B" />
 <b deltaxml:deltaV2="B" />
 <c deltaxml:deltaV2="A=B" />
 <d deltaxml:deltaV2="A=B" />
 <e deltaxml:deltaV2="B" />
</xmldoc>

Quindi otterresti qualcosa di molto simile per il tuo secondo confronto, da C a D dove C è come A ma D ha un elemento aggiunto (nota che abbiamo chiamato A e B qui in modo da ottenere un risultato il più vicino al primo risultato come possiamo):

<xmldoc deltaxml:deltaV2="A!=B" deltaxml:version="2.0" deltaxml:content-type="full-context" xmlns:deltaxml="http://www.deltaxml.com/ns/well-formed-delta-v1">
 <a deltaxml:deltaV2="A=B" />
 <b deltaxml:deltaV2="B" />
 <f deltaxml:deltaV2="B" />
 <c deltaxml:deltaV2="A=B" />
 <d deltaxml:deltaV2="A=B" />
 <e deltaxml:deltaV2="B" />
</xmldoc>

Questo è un confronto bidirezionale di base, che è disponibile per .NET. Come puoi vedere, puoi confrontare questi due risultati e ottenere una differenza utile (alcune modifiche dello spazio dei nomi dovrebbero essere apportate in modo che i file delta fossero trattati come file normali).

È anche possibile utilizzare l'unione XML (sebbene sia solo Java) per migliorare uno stadio e mostrare tutti e tre i file in uno. Dato che A è uguale a C, possiamo considerarlo uno, quindi vogliamo conoscere le modifiche tra A e B e tra A e D.

<xmldoc deltaxml:deltaV2="A!=B!=D" deltaxml:version="2.0" deltaxml:content-type="full-context" xmlns:deltaxml="http://www.deltaxml.com/ns/well-formed-delta-v1" xmlns:dxu="http://www.deltaxml.com/ns/unified-delta-v1">
 <a deltaxml:deltaV2="A=B=D" />
 <b deltaxml:deltaV2="B=D" />
 <f deltaxml:deltaV2="D" />
 <c deltaxml:deltaV2="A=B=D" />
 <d deltaxml:deltaV2="A=B=D" />
 <e deltaxml:deltaV2="B=D" />

Questo è probabilmente ciò di cui hai bisogno qui. Non dici qual è il tuo obiettivo finale, forse per creare uno stile di modifica simultaneo dell'aggiornamento, cioè unisci le modifiche apportate in entrambi i percorsi di modifica. Come hai trovato, questo è abbastanza difficile! Spero che questo possa essere d'aiuto. Robin

    
risposta data 15.11.2016 - 13:02
fonte

Leggi altre domande sui tag