XSL / Die XSLT - Struktur / XPath 3.1: Map, xsl:map / 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 XQuery-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.
V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn
☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de