Was ist XQuery? / XQuery: WHERE und Nummerierung

XQuery: WHERE und Nummerierung

XQuery: WHERE und Nummerierung

➪ Die WHERE-Klausel filtert aus der Liste jener Nodes, die im vorhergehenden XPath-Statement angesprochen werden, jene heraus, die den WHERE-Kriterien entsprechen. Sollen die gefundenen Nodes in der Ausgabe nummeriert werden, kann die WHERE-Klausel kontraproduktiv sein.

Bereits vorhin haben Sie sich einen XQuery-Loop der Art for $y at $p in ... angesehen, wo $y das jeweilige Item repräsentierte und $p dessen Position in der Sequenz. Hier noch einmal ein Beispiel für den späteren Vergleich:


<erg>{
  for $m at $p in /Orte/Ort[1]/Mensch return 
    <m p="{$p}" id="{$m/id}">
      {$m/vorname/text()}
    </m>
}</erg>

Das Ergebnis ist eine Nodeliste. Das jeweilige Attribut p stellt die jeweilige Position dar; das Attribut id repräsentiert den Elementinhalt aus dem Quelldokument. So weit, so gut:


<erg>
  <m p="1" id="1">Hugo</m>
  <m p="2" id="4">Nicole</m>
  <m p="3" id="9">Stefan</m>
  <m p="4" id="2">Stefan</m>
  <m p="5" id="3">Siggi</m>
  <m p="6" id="7">Heini</m>
</erg>

Nun ändern Sie die XQuery-Logik: Nach dem for $m at $p in /Orte/Ort[1]/Mensch"-Loop fügen Sie die Einschränkung where $m/id/text() > 2 ein.


<erg>
{
for $m at $p in /Orte/Ort[1]/Mensch
where $m/id/text() > 2
return 
<m p="{$p}" id="{$m/id}">
  {$m/vorname/text()}
</m>
}
</erg>

Das Ergebnis ist wie gewünscht: Es werden nur Items mit einer id größer als 2 ausgegeben: "3, 9, 4, 7". Aber halt, da stimmt doch was nicht! Was ist mit der Nummerierung im Attribut p? Die Reihenfolge "2, 3, 5, 6" ist (genau genommen) etwas lückenhaft. Ich hätte "1, 2, 3, 4" erwartet.

Es sieht so aus, als würde for $m at $p in /Orte/Ort[1]/Mensch-Loop im Speicher die ursprüngliche Reihenfolge komplett generieren und anschließend mit der where-Einschränkung aus dieser Reihenfolge jene Elemente löschen, die der Einschränkung unterliegen.


<erg>
  <m p="2" id="4">Nicole</m>
  <m p="3" id="9">Stefan</m>
  <m p="5" id="3">Siggi</m>
  <m p="6" id="7">Heini</m>
</erg>

In XSL-Syntax wäre der Effekt derselbe, wenn Sie die folgende Logik implementiert hätten:


<erg>
  <xsl:for-each select="/Orte/Ort[1]/Mensch">
   <xsl:if test="id &gt; 2">
    <m p="{position()}" id="{id}">
     <xsl:value-of select="vorname" />
    </m>
   </xsl:if>
  </xsl:for-each>
</erg>

Wie kommen Sie nun zur korrekten Nummerierung? Recht einfach: Sie müssen mit einem passgenauen XPath-Statement (/Orte/Ort[1]/Mensch[id > 2]) dafür sorgen, dass von vornherein nur die relevanten Nodes in der Sequenz auftauchen. Dann passt die Nummerierung sofort, und die WHERE-Einschränkung entfällt.


<erg>
{
for $m at $p in /Orte/Ort[1]/Mensch[id > 2]
return 
<m p="{$p}" id="{$m/id}">
  {$m/vorname/text()}
</m>
}
</erg>

In XSL ist das Vorgehen analog: Präzise Arbeit mit XPath.


 <erg>
  <xsl:for-each 
       select="/Orte/Ort[1]/Mensch[id &gt; 2]">
   <m p="{position()}" id="{id}">
    <xsl:value-of select="vorname" />
   </m>
  </xsl:for-each>
 </erg>

Und dann stimmt's auch mit der Nummerierung:


<erg>
  <m p="1" id="4">Nicole</m>
  <m p="2" id="9">Stefan</m>
  <m p="3" id="3">Siggi</m>
  <m p="4" id="7">Heini</m>
</erg>

Aus diesem Grunde empfehle ich eine präzise Arbeit mit XPath-Statements, auch dann, wenn es nicht um Nummerierung geht.

wg / 14. Juli 2018



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf.






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/XQuery7.html