XML * XML-SCHEMA * XPATH * XSL * XSL-FO * SVG * XQUERY * XPROC * ANT * DIVERSES



XSL / Die XSLT - Struktur / XPath 3.1: Map, xsl:map / XPath: map:merge

XPath: map:merge

XPath: map:merge

map:merge kombiniert die Inhalte mehrerer Maps in eine neue Map, die wiederum ausgewertet werden kann.

Signaturen:


map:merge($maps as map(*)*) as map(*)
map:merge($maps as map(*)*, $options as map(*)) as map(*)

Siehe https://www.w3.org/TR/xpath-functions-31/#func-map-merge

Ein gutes Beispiel finden Sie in Gruppierungen. Weitere Beispiele:


<xsl:template match="/">
  <root>
   <size nr="2">
    <xsl:value-of 
         select="map:size(
                     map:merge(
                          ($vmap, map{3:'Zenzi Zwecklos'})
                     ))"/>
   </size>
   <keys nr="2">
    <xsl:for-each 
         select="map:keys(
                     map:merge(
                         ($vmap, map{3:'Zenzi Zwecklos'})
                     ))">
     <key>
      <xsl:value-of select="."/>
     </key>
    </xsl:for-each>
   </keys>
  </root>
</xsl:template>

Die merged map ist durch map:size bzw. map:keys auswertbar:


<root>
 <size nr="2">4</size>
 <keys nr="2">
  <key>0</key>
  <key>1</key>
  <key>2</key>
  <key>3</key>
 </keys>
</root>

Hier möchte ich auf den Konfliktfall hinweisen, dass beim Mergen zweier Maps ein Schlüssel doppelt auftauchen könnte. Dieser Fall wird in der XSL-Variablen vmap2 abgebildet.


<xsl:template match="/">
  <root>
   <merge nr="2">
    <xsl:variable name="vmap2" 
         select="map:merge(($vmap, map{1:'Zenzi Zwecklos'}))"/>
    <xsl:for-each select="map:keys($vmap2)">
     <key nr="{.}">
      <xsl:value-of select="map:get($vmap2, .)"/>
     </key>
    </xsl:for-each>   
   </merge>
  </root>
</xsl:template>

Der verwendete XSL-Prozessor hat den ursprünglichen Wert beibehalten:


<root>
 <merge nr="2">
  <key nr="0">Hugo Holzflos</key>
  <key nr="1">Lotte Rielos</key>
  <key nr="2">Resi Denzschlos</key>
 </merge>
</root>

Bei der Verarbeitung dieser Fälle muss betrachtet werden, inwieweit die Schlüssel wirklich gleich, d.h. auch von demselben Datentyp sind. Das ist beispielsweise nicht der Fall, wenn der Schlüssel "1" als xs:string gecastet wird.


<xsl:variable 
     name="vmap2" 
     select="map:merge(($vmap, 
                 map{xs:string(1):'Zenzi Zwecklos'}))"/>

Unter dem Stichwort op:same-key können Sie im Web einige Bedingungen finden, die bei der Prüfung der Map-Schlüssel zu beachten sind, u.a., dass beide Schlüssel den Anforderungen von fn:deep-equal entsprechen. Darüber hinaus können Sie spezielle Duplikat-Handler in Form von (auch anonymen) Funktionen implementieren, in denen das nähere Verfahren hinsichtlich use-first, use-last, combine, reject oder use-any festgelegt wird.

Im Übrigen ist die automatische Generierung komplexer Maps mit map:merge, map:entry, fn:for-each und function sehr effizient:


<fn_for-each>
  <xsl:variable name="vmap5" 
        select="map:merge(($vmap, 
              fn:for-each(
                 (10 to 20)[. mod 2 = 1], 
                 function($p1){map:entry($p1, $p1*100)}
              )
        ))"/>
        <xsl:for-each select="map:keys($vmap5)">
    <key nr="{.}">
      <xsl:value-of select="map:get($vmap5, .)"/>
    </key>
  </xsl:for-each>
</fn_for-each>

Das Ergebnis lautet:


<root>
  <fn_for-each>
    <key nr="0">Hugo Holzflos</key>
    <key nr="1">Lotte Rielos</key>
    <key nr="2">Resi Denzschlos</key>
    <key nr="11">1100</key>
    <key nr="13">1300</key>
    <key nr="15">1500</key>
    <key nr="17">1700</key>
    <key nr="19">1900</key>
  </fn_for-each>
</root>

Der Vollständigkeit halber finden Sie hier noch eine -Variante, in der die ursprüngliche map "$vvar" um mehrere Maps ergänzt wurde. Damit das problemlos klappt, muss jede Map ihren eigenen Schlüssel haben.


declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
<erg>
  {
    let $vvar := map{
         0:'Hugo Holzflos', 
         1:'Lotte Rielos', 
         2:'Resi Denzschlos'}
    let $vmerged := map:merge(($vvar, 
        map{3:'Zenzi Zwecklos'}, 
        map{4:'Wilma Wunschlos'}, 
        map{5:'Theo Traumlos'}))
    for $x in map:keys($vmerged)
    return
      <WERT
        key="{$x}">  
        {map:get($vmerged, $x)}
      </WERT>
  }
</erg>

Das Ergebnis dieses Aufrufs sehen Sie hier:


<erg>
  <WERT key="0">Hugo Holzflos</WERT>
  <WERT key="1">Lotte Rielos</WERT>
  <WERT key="2">Resi Denzschlos</WERT>
  <WERT key="3">Zenzi Zwecklos</WERT>
  <WERT key="4">Wilma Wunschlos</WERT>
  <WERT key="5">Theo Traumlos</WERT>
</erg

wg / 7. April 2020



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