16. Oktober 2007

SQL-Funktion XMLDIFF: Unterschiede in XML-Dokumenten erkennen

Das Vergleichen zweier XML-Dokumente ist keine einfache Aufgabe - einfach weil gleiche Dinge nach dem dem XML-Standard unterschiedlich ausgedrückt werden können. Hier sind einige Beispiele für textlich unterschiedliche XML-Dokumente, die jedoch inhaltlich gleich sind:
  • XML-Tags ohne Inhalt:
    1. <xml-tag/>
    2. <xml-tag></xml-tag>
  • Whitespace:
    1. <xml-tag>
        </xml-tag>
    2. <xml-tag></xml-tag>
  • Namespace-Präfix:
    1. <a:xml-tag xmlns:a="my-namespace"></a:xml-tag>
    2. <xml-tag xmlns="my-namespace"></xml-tag>
  • Entity Referenzen:
    1. <xml-tag>"</xml-tag>
    2. <xml-tag>&quot;</xml-tag>
An diesen Beispielen ist gut erkennbar, dass ein einfacher Textvergleich von XML-Dokumenten zu kurz greift. Insbesondere die Namespaxe-Präfixe werden häufig aus der Anwendung heraus generiert; so dass unterschiedliche Namespace-Präfixe völlig normal sind. Ein Vergleichsalgorithmus sollte daher erkennen, dass semantisch kein Unterschied zwischen den XML-Dokumenten besteht: gerade wenn Änderungen auf ein anderes System übertragen werden sollen, ist das sehr wichtig - sonst verschwendet man unnötig Netzbandbreite und Rechnerkapazität.
Oracle11g bringt hierfür neue SQL-Funktionen mit: XMLDIFF und XMLPATCH. Ein Beispiel für den Vergleich zweier unterschiedlicher Dokumente:
select xmldiff(
  xmltype('<xml-tag></xml-tag>'),
  xmltype('<xml-tag>Inhalt</xml-tag>')
) from dual
/

<xd:xdiff xsi:schemaLocation="http://xmlns.oracle.com/xdb/xdiff.xsd http://xmlns.oracle.com/xdb/xdiff.xsd" 
          xmlns:xd="http://xmlns.oracle.com/xdb/xdiff.xsd" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <?oracle-xmldiff operations-in-docorder="true" output-model="snapshot" diff-algorithm="global"?>
  <xd:append-node xd:node-type="text" xd:parent-xpath="/xml-tag[1]">
    <xd:content>Inhalt</xd:content>
  </xd:append-node>
</xd:xdiff>
Der fettgedruckte Teil repräsentiert die Unterschiede ... und zwar schon direkt in einem "Patch"-fähigen Format: Die Ausgabe der XMLDIFF-Funktion kann direkt von der XMLPATCH-Funktion verwendet werden - um die Änderungen direkt auf ein anderes XML-Dokument anzuwenden. XMLDIFF und XMLPATCH können also kombiniert genutzt werden, um Deltas in XML-Dokumenten zu erkennen und auf andere Systeme zu übertragen. Doch nun kommt die XML-Besonderheit: Vergleicht man mit XMLDIFF zwei textlich verschiedene, inhaltlich jedoch gleiche XML-Dokumente, so ergibt sich folgendes:
select xmldiff(
  xmltype('<xml-tag></xml-tag>'),
  xmltype('<xml-tag/>')
) from dual
/

<xd:xdiff xsi:schemaLocation="http://xmlns.oracle.com/xdb/xdiff.xsd http://xmlns.oracle.com/xdb/xdiff.xsd" 
          xmlns:xd="http://xmlns.oracle.com/xdb/xdiff.xsd" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <?oracle-xmldiff operations-in-docorder="true" output-model="snapshot" diff-algorithm="global"?>
</xd:xdiff>

Keine Kommentare:

Beliebte Postings