Gern stehe ich zur fachlichen Unterstützung in XML-Technologien, C#.NET, VisualBasic.NET und Java zur Verfügung. Sprechen Sie mich einfach an: Mail oder ☎ 0151 . 750 360 61


XPath 3.0, XPath 2.0, XPath 1.0 / XPath-Funktionen / XPath: Sequenz-Funktionen / XPath: for-each

XPath: for-each

XPath: for-each

➪ Die XPath-Funktion for-each fordert zwei Parameter ein: a) ein oder mehrere Items als Sequenz, b) eine Funktion, die für jedes Item dieser Sequenz aufgerufen wird.

Auf dieser Seite:

Verwendung findet die anonyme Funktion auch in der XPath-Funktion for-each, die zwei Parameter einfordert:

So generieren die Argumente


  <xsl:template match="/">
    <root>
      <xsl:for-each 
           select="fn:for-each(
                      (10 to 20)[. mod 2 = 1], 
                      function($p1){$p1*100})">
        <wert>
          <xsl:value-of select="."/>
        </wert>
      </xsl:for-each>
    </root>
  </xsl:template>

... dieses Ergebnis:


<root>
  <wert>1100</wert>
  <wert>1300</wert>
  <wert>1500</wert>
  <wert>1700</wert>
  <wert>1900</wert>
</root>

Die Lösung mit XQuery

Dasselbe Ergebnis erhalten Sie beim Aufruf der for-each-Funktion in XQuery:


<root>
{
  for $x in fn:for-each(
            (10 to 20)[. mod 2 = 1], 
            function($p1){$p1*100})
  return 
    <wert>     
      {$x}
    </wert>
}
</root>

Grundsätzlich empfehlenswert ist die typsaubere Parameterübergabe sowie die Deklaration des Rückgabetyps der Funktion, in diesem Fall also xs:integer. Der Aufruf generiert dasselbe Ergebnis wie vorher.


<root>
{
  for $x in fn:for-each(
            (10 to 20)[. mod 2 = 1], 
            function($p1 as xs:integer) 
                    as xs:integer 
                    {$p1*100}
             )
  return 
    <wert>     
      {$x}
    </wert>
}
</root>

Siehe auch , .

Sequenz transformieren und filtern

In Lambda-Expressions in Java habe ich in map / filter / reduce ein Beispiel gezeigt, wie die Werte einer Integer-Sequenz (stream) quadriert und anschliessend gefiltert (alle Werte, die ohne Rest durch 3 teilbar sind) werden. Das kriegen Sie problemlos auch mit for-each hin:


<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <ergebnis>
            <xsl:for-each select="for-each(
                    (5 to 19), 
                    function($p1){$p1*$p1}) [. mod 3 = 0]">
                <wert>
                    <xsl:value-of select="."/>
                </wert>
            </xsl:for-each>
        </ergebnis>
    </xsl:template>
</xsl:stylesheet>

Das Zwischenergebnis lautet:


<ergebnis>
   <wert>36</wert>
   <wert>81</wert>
   <wert>144</wert>
   <wert>225</wert>
   <wert>324</wert>
</ergebnis>

Und wenn Sie die Werte summieren, kommt dasselbe Ergebnis heraus:


<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <ergebnis>
            <xsl:for-each 
                select="sum(
                        for-each(
                            (5 to 19), 
                            function($p1){$p1*$p1}) [. mod 3 = 0]
                        )">
                <wert>
                    <xsl:value-of select="."/>
                </wert>
            </xsl:for-each>
        </ergebnis>
    </xsl:template>
</xsl:stylesheet>

Resultat:


<ergebnis>
   <wert>810</wert>
</ergebnis>

Dasselbe mit XQuery:


<ergebnis><wert>{
    sum(
        for-each(
            (5 to 19),
            function ($p1) {
                $p1 * $p1
            })[. mod 3 = 0]            
    )
}</wert></ergebnis>

Die Schritte können Sie auch in einer definieren.

Kumulierte Ergebnisse mit sum und for-each

Sie benötigen nicht nur einen Einzelwert, sondern auch die Zwischenergebnisse? Kein Problem:


 element {'ergebnis'}{ 
    for $w in (1 to 10) return element {'value'}{
        attribute {'i'}{$w},
        attribute {'kumuliert'}{
            sum(
                for-each(
                       (  1 to (xs:int($w))  ),                     
                       function($a){$a}
                  )
            )
        }
    }    
 } 

Das Resultat:


<ergebnis>
   <value i="1" kumuliert="1"/>
   <value i="2" kumuliert="3"/>
   <value i="3" kumuliert="6"/>
   <value i="4" kumuliert="10"/>
   <value i="5" kumuliert="15"/>
   <value i="6" kumuliert="21"/>
   <value i="7" kumuliert="28"/>
   <value i="8" kumuliert="36"/>
   <value i="9" kumuliert="45"/>
   <value i="10" kumuliert="55"/>
</ergebnis

Siehe auch und .

wg / 1. Mai 2019



Fragen? Anmerkungen? Tipps?

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