Was ist XQuery? / XPath 3.1: Arrays in XQuery

XPath 3.1: Arrays in XQuery

XPath 3.1: Arrays in XQuery

➪ Auch die erweiteren Funktionen von XPath 3.1, zum Beispiel die Array-Funktionen, stehen in XQuery zur Verfügung. Voraussetzung ist die Einbindung des speziellen Namespaces.


declare namespace 
   array = "http://www.w3.org/2005/xpath-functions/array";

Damit ausgerüstet, ist es ein Leichtes, ein zu definieren und auszuwerten. Die Schleife geht von 1 bis zur Array-Größe; über array:get wird der Wert an der jeweiligen Stelle ausgelesen.


<erg>
  {
    let $vvar := ['Hugo', 'Lotte', 'Theo']
    for $x in 1 to array:size($vvar)
    return
      <WERT
        name="{$x}">
        {array:get($vvar, $x)}
      </WERT>
  }
</erg>

Das Ergebnis ist dann:


<erg>
   <WERT name="1">Hugo</WERT>
   <WERT name="2">Lotte</WERT>
   <WERT name="3">Theo</WERT>
</erg

array:reverse

Die ursprüngliche Reihenfolge des Arrays können wir mit array:reverse leicht umkehren.


<erg>
  {
    let $vvar := ['Hugo', 'Lotte', 'Theo']
    let $vrev := array:reverse($vvar)
    for $x in 1 to array:size($vrev)
    return
      <WERT
        name="{$x}">
        {array:get($vrev, $x)}
      </WERT>
  }
</erg>

Das Ergebnis ist dann:


<erg>
   <WERT name="1">Theo</WERT>
   <WERT name="2">Lotte</WERT>
   <WERT name="3">Hugo</WERT>
</erg

array:subarray

Auch das Subarray läßt sich definieren: im folgenden Fall werden aus dem ursprünglichen Array ab dem zweiten Arrayfeld drei weitere Werte entnommen und wie vorher ausgegeben.


<erg>
  {
    let $vvar := ['Hugo', 'Lotte', 'Theo', 'Alfons', 'Niki']
    let $vsubarray := array:subarray($vvar, 2, 3) 
    for $x in 1 to array:size($vsubarray)
    return
      <WERT
        name="{$x}">
        {array:get($vsubarray, $x)}
      </WERT>
  }
</erg>

Das Ergebnis ist dann:


<erg>
   <WERT name="1">Lotte</WERT>
   <WERT name="2">Theo</WERT>
   <WERT name="3">Alfons</WERT>
</erg

array:insert-before, array:tail

Während wir mit "array:insert-before" in einem Array an einer bestimmten Stelle (hier: vor der 3. Stelle) einen weiteren Wert einfügen können (das Array umfaßt nunmehr die Reihenfolge 'Hugo', 'Lotte', 'Tanja', 'Theo'), unterstützt uns "array:tail" darin, alle Felder anzusprechen, ausgenommen das erste.


<erg>
  {
    let $vvar := ['Hugo', 'Lotte', 'Theo']
    let $vib := array:insert-before($vvar, 3, 'Tanja')
    let $vtail := array:tail($vib)
    for $x in 1 to array:size($vtail)
    where array:get($vtail, $x) != 'Tanja'
    return
      <WERT
        name="{$x}">
        {array:get($vtail, $x)}
      </WERT>
  }
</erg>

Die Ausgabe lautet daher folgerichtig:


<erg>
   <WERT name="1">Lotte</WERT>
   <WERT name="2">Tanja</WERT>
   <WERT name="3">Theo</WERT>
</erg

Leicht erweitert, können wir nun mit der "WHERE"-Klausel dafür sorgen, daß 'Tanja' nicht ausgegeben wird.


<erg>
  {
    let $vvar := ['Hugo', 'Lotte', 'Theo']
    let $vib := array:insert-before($vvar, 3, 'Tanja')
    let $vtail := array:tail($vib)
    for $x in 1 to array:size($vtail)
    where array:get($vtail, $x) != 'Tanja'
    return
      <WERT
        name="{$x}">
        {array:get($vtail, $x)}
      </WERT>
  }
</erg>

Die Ausgabe lautet daher mit der ursprünglichen Numerierung ('Tanja' an Platz 2 fehlt):


<erg>
   <WERT name="1">Lotte</WERT>
   <WERT name="3">Theo</WERT>
</erg

array:for-each

Die array:for-each - Funktion durchläuft ihrerseits die Bestandteile des Arrays. Durch eine zusätzliche interne Funktion läßt sich jeder Einzelwert modifizieren.

So prüft der folgende Aufruf, ob der Feldinhalt einem regulären Ausdruck entspricht: das erste Zeichen muß entweder "T" oder "H", die restlichen Buchstaben klein sein. In diesem Fall wird der gesamte Feldinhalt groß geschrieben, andernfalls ist der Feldinhalt leer.


<erg>
  {
    let $vvar := ['Hugo', 'Lotte', 'Theo']
    let $vvar2 := array:for-each($vvar, 
       function($v){ if (fn:matches($v, '^[TH][a-z]+') ) 
                     then ( fn:upper-case($v) ) 
                     else ( ) })
    for $x in 1 to array:size($vvar2)
    return
      <WERT
        name="{$x}">
        {array:get($vvar2, $x)}
      </WERT>
  }
</erg>

Das Ergebnis lautet daher:


<erg>
   <WERT name="1">HUGO</WERT>
   <WERT name="2"/>
   <WERT name="3">THEO</WERT>
</erg

array:for-each-pair

array:for-each-pair erlaubt, Wertepaare zu bilden und diese durch eine interne Funktion miteinander zu verknüpfen. Im folgenden Beispiel werden die drei Wertepaare (9, 36), (5, 82) und (3, 57) gebildet, wobei in der Funktion (nach Prüfung, ob der Wert auch eine xs:integer-Zahl ist) die jeweils erste Zahl von der zweiten Zahl subtrahiert wird. Damit ergeben sich folgende Ergebnisse:

36 - 9 27
81 - 5 76
57 - 3 54

<erg>
    {
        let $vvar := array:for-each-pair(
             array{ (9, 5, 3) }, 
             array{ (36, 81, 57) }, 
             function($p1 as xs:integer, $p2  as xs:integer)  
                     as xs:integer 
                     { $p2 - $p1})
        for $x in 1 to array:size($vvar)
        return
            <WERT
                name="{$x}">
                {array:get($vvar, $x)}
            </WERT>
    }
</erg>

Das Ergebnis lautet daher:


<erg>
   <WERT name="1">27</WERT>
   <WERT name="2">76</WERT>
   <WERT name="3">54</WERT>
</erg

Und wenn wir die Summe dieser subtrahierten Wertepaare haben möchten, so steht die altbewährte sum-Funktion gern bereit ...


<erg>
    {
        let $vvar := array:for-each-pair(
             array{ (9, 5, 3) }, 
             array{ (36, 81, 57) }, 
             function($p1 as xs:integer, $p2  as xs:integer)  
                     as xs:integer 
                     { $p2 - $p1})
        return sum($vvar)        
    }
</erg>

... und beglückt uns mit diesem Resultat:


<erg>157</erg

wg / 22. März 2018



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf:

Vorname
Nachname
Mailadresse







Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/XQuery15.html