fn:deep-equal

(Auszug aus "XSLT 2.0 & XPath 2.0" von Frank Bongers, Kapitel 5.)

A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z

   

Kategorie: Funktionen für Sequenzen

Herkunft: XPath 2.0

Rückgabewert: Ein Boolescher Wert xs:boolean; der Wert true oder false, je nachdem, ob die verglichenen Sequenzen in Werten und Reihenfolge der Items übereinstimmen oder nicht

Aufruf/Argumente:

fn:deep-equal($sequenz1, $sequenz2, $collation-URI?)

$sequenz1:
Eine Sequenz aus einer beliebigen Anzahl von Items beliebigen Typs. Ist die erste Sequenz leer, so gibt die Funktion false zurück, sofern die zweite Sequenz nicht ebenfalls leer ist. Beim Vergleich zweier Sequenzen durch fn:deep-equal() spielt die Reihenfolge der Übergabe keine Rolle.

$sequenz2:
Eine Sequenz aus einer beliebigen Anzahl von Items beliebigen Typs. Ist die zweite Sequenz leer, so gibt die Funktion false zurück, sofern die erste Sequenz nicht ebenfalls leer ist.

$collation-URI:
Optional. Das dritte Argument besteht aus einem String xs:string, der den URI-String der anzuwendenden Collation benennt. Der Wert muss lexikalisch dem Typ xs:anyURI entsprechen. Ist dies nicht der Fall, wird eine Fehlermeldung ausgegeben (»Invalid collationURI«). Wird kein drit­tes Argument übergeben, so wird für Vergleiche von Stringwerten die Default-Collation herangezogen. Sind in den zu vergleichenden Sequenzen keine Items vom Typ xs:string enthalten, so wird die Collation-Anweisung ignoriert.

Verwendungszweck:

Die Funktion fn:deep-equal() dient dazu, die Gleichheit – nicht die Identität! – zweier Sequenzen festzustellen, und gibt genau dann den Booleschen Wert true zurück, wenn alle Items beider Sequen­zen einander paarweise in der übergebenen Reihenfolge wertmäßig entsprechen.

Sind beide Eingangssequenzen leer, so gibt die Funktion true zurück. Sind die Sequenzen nicht leer, aber von unterschiedlicher Länge, so gibt sie false zurück. Beim Vergleich wird verschieden vorgegangen, je nachdem, ob es sich bei den jeweils verglichenen Items um atomare Werte oder Knoten handelt.

Vergleich von Items mit atomaren Werten:
Korrespondierende Items mit atomaren Werten werden direkt miteinander verglichen, wobei der Vergleich gemäß des eq-Operators vorgenommen wird. Für alle atomaren Typen mit Aus­nahme von Strings kann die Gleichheit unmittelbar anhand der Werte festge­stellt werden.

Ausnahme beim Vergleich des Wert NaN:
Besitzen zwei zu vergleichende numerische Items den Wert NaN, so gelten sie nicht als gleich (laut Definition des Operators op:numeric-equal()).

Für Vergleiche zwischen Strings wird entweder die Default-Collation herange­zogen oder die als drittes Argument genannte Collation. Der eigentliche Ver­gleich entspricht dem Vorgehen bei fn:compare(), wobei es in diesem Fall lediglich auf Gleichheit oder Ungleichheit ankommt.

Vergleich von Nodes:
Handelt es sich bei zwei zu vergleichenden Items um Nodes, so muss ein Vergleich ihrer Inhalte auf allen tiefer liegenden Hierar­chieebenen vorgenommen werden, um Gleichheit festzustellen (deep equal). Enthält der getestete Node im Inneren weitere Nodes, so muss der Test rekursiv angewendet werden.

Für die Feststellung der Gleichheit zweier Nodes ist es nicht erforderlich, dass beide Nodes die gleiche Typannotation und die gleichen, in ihrem Bereich gültigen Namensräume besitzen. Für die unmittelbar als Teile der Sequenzen vergli­chenen Nodes spielt ebenfalls weder deren Elternknoten noch deren Basis-URI eine Rolle.

Handelt es sich bei den verglichenen Knoten um Elementknoten, so hat die Reihen­folge eventueller Attribute keine Bedeutung (wohl aber ihr Vorhandensein und ihr Wert). Relevant ist jedoch die Reihenfolge eventuell enthaltener Kindknoten, mit Ausnahme von Kommentaren und Pro­cessing-Instructions. Letztere spielen bei dem Vergleich nur dann eine Rolle, wenn sie unmittelbar als Items in den übergebenen Sequenzen erscheinen und werden ansonsten – da nicht informationstragend – nicht berücksichtigt.

Einfach ausgedrückt, gelten zwei Nodes dann als gleich, wenn sie selbst gleich sind, über gleiche Attribute verfügen und ihre Kindknoten (ausgenommen Kommen­tare und PIs) in vorgegebener Reihenfolge paarweise gleich sind.

Genauer betrachtet schlägt der Vergleich dann fehl, wenn:

  • Beide Nodes zu verschiedenen Gattungen (node kinds) gehören
  • Beide Nodes QNames als Bezeichner besitzen, die sich in expandierter Form unterscheiden
  • Es sich bei den verglichenen Nodes um Textknoten, Kommentare, Processing-Instructions oder Namensraumknoten handelt, deren Stringwerte auf Grundlage der verwendeten Collation ungleich sind.
  • Es sich um Attributknoten oder Elementknoten mit einfachem Inhalt (simple content) handelt, deren Inhalte, gemäß der Anwendung von fn:data() als xs:untypedAtomic bewertet, auf Grundlage der verwendeten Collation ungleich sind.
  • Es sich um Elementknoten mit Attributen handelt und nicht für jedes Attribut ein gleichnamiges Pendant mit gleichem Stringwert existiert.
  • Es sich um Elementknoten mit Kindknoten handelt und für einen der Kindkno­ten (ohne Berücksichtigung von Kommentaren und PIs) die Anwendung von fn:deep-equal() fehlschlägt.

Beispiel – Vergleich zweier Nodes:

Das Quelldokument:

<?xml version="1.0" encoding="UTF-8"?>
<beispiel>
  <test>
    <a><b><c/></b></a>
  </test>
  <test>
    <a><b><c/></b></a>
  </test>
  <test>
    <a><anders/></a>
  </test>
</beispiel>

Das Dokument enthält dreimal ein Element <test>, zweimal mit identischem, einmal mit abweichendem Inhalt.

Das Stylesheet (Auszug):

<xsl:template match="beispiel">
  <ergebnis> 
    Node 1 und Node 1 sind "deep-equal": 
    <xsl:value-of select="fn:deep-equal((test[1]), (test[1]))"/>
    Node 1 und Node 2 sind "deep-equal": 
    <xsl:value-of select="fn:deep-equal((test[1]), (test[2]))"/>
    Node 1 und Node 3 sind "deep-equal": 
    <xsl:value-of select="fn:deep-equal((test[1]), (test[3]))"/>
  </ergeb­nis>
</xsl:template>

Die Funktion fn:deep-equal() erhält als Eingabewert zwei Sequenzen aus je einem Node des Quelldokuments.

Das Ergebnis:

<?xml version="1.0" encoding="UTF-8"?>
<ergebnis> 
  Node 1 und Node 1 sind "deep-equal": true
  Node 1 und Node 2 sind "deep-equal": true
  Node 1 und Node 3 sind "deep-equal": false
</ergebnis>

Die Funktion stellt die Gleichheit der ersten und zweiten Instanz des Elements <test> und die Ungleichheit der ersten und dritten fest.

Die Funktion stellt zwar ebenfalls die Gleichheit der ersten Instanz des Ele­ments mit sich selbst fest – dies ist jedoch als Test auf Identität nicht geeig­net.

Funktionsdefinition:

XPath 1.0:

Funktion nicht verfügbar

XPath 2.0:

fn:deep-equal($parameter1 as item()*, 
              $parameter2 as item()*) as xs:boolean

fn:deep-equal($parameter1 as item()*, 
              $parameter2 as item()*, 
              $collation as string) as xs:boolean

   

<< zurück vor >>
Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © Galileo Press, Bonn 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT 2.0 & XPath 2.0 ― Das umfassende Handbuch" denselben Bestimmungen wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Galileo Press, Rheinwerkallee 4, 53227 Bonn