Lors de la migration de mes albums photo de Gellery vers WordPress, j’ai du transformer des fragments XML tels que :
<row> <field name="g_id">22909</field> <field name="g_description" xsi:nil="true" /> <field name="g_keywords" xsi:nil="true" /> <field name="g_summary" xsi:nil="true" /> <field name="g_title">dsc00001</field> <field name="g_pathComponent">aaa.jpg</field> <field name="g_pathComponent">011120-Forum-XML-2001</field> <field name="g_orderWeight">1000</field> </row>
En instruction SQL telles que :
update wp_ngg_gallery g, wp_ngg_pictures p set p.image_slug = "dsc00001", p.description = "dsc00001", p.alttext = "dsc00001", p.sortorder = 1 where p.galleryid = g.gid and g.title = "011120-Forum-XML-2001" and p.filename = "aaa.jpg";
Ce n’est pas bien compliqué, mais la méthode classique pour faire cela en XSLT est bestiale, répétitive, ennuyeuse et illisible… Cela donne quelque chose comme :
<xsl:template match="row"> <xsl:variable name="title" select="if (field[@name='g_title'] != '') then field[@name='g_title'] else field[@name='g_pathComponent'][1]"/> <xsl:variable name="description" select="if (field[@name='g_description'] != '') then field[@name='g_description'] else $title"/> <xsl:variable name="summary" select="if (field[@name='g_summary'] != '') then field[@name='g_summary'] else $title"/> <xsl:text><![CDATA[update wp_ngg_gallery g, wp_ngg_pictures p set p.image_slug = "]]></xsl:text> <xsl:value-of select="$title"/> <xsl:text><![CDATA[", p.description = "]]></xsl:text> <xsl:value-of select="$description"/> <xsl:text><![CDATA[", p.alttext = "]]></xsl:text> <xsl:value-of select="$summary"/> <xsl:text><![CDATA[", p.sortorder = ]]></xsl:text> <xsl:value-of select="position()"/> <xsl:text><![CDATA[ where p.galleryid = g.gid and g.title = "]]></xsl:text> <xsl:value-of select="field[@name='g_pathComponent'][2]"/> <xsl:text><![CDATA[" and p.filename = "]]></xsl:text> <xsl:value-of select="field[@name='g_pathComponent'][1]"/> <xsl:text><![CDATA["; ]]></xsl:text> </xsl:template>
En tapant ce galimatia je ne pu m’empêcher de penser à la manière dont j’aurais pu faire cela en Python :
print '''
update
wp_ngg_gallery g,
wp_ngg_pictures p
set
p.image_slug = "%(title)",
p.description = "%(description)",
p.alttext = "%(alttext)",
p.sortorder = %(sortOrder)
where
p.galleryid = g.gid
and g.title = "%(galleryTitle)"
and p.filename = "%(filename)";
''' % {"title": ..., "description: ...", ...}
Ne trouvez vous pas cela bien plus simple et plus élégant?
La bonne nouvelle, c’est que c’est très simple à implémenter en XSLT 2.0!
J’ai choisi une syntaxe « ${param-name} »plutôt que « %(param-name) » comme en Python, mais vous pourrez facilement adapter mon implémentation si vous préférez rester « pythonique »… Il suffit en fait de définir ce « template » nommé :
<xsl:template name="template">
<xsl:param name="template"/>
<xsl:param name="parameters"/>
<xsl:analyze-string select="$template" regex="\$\{{(\i\c*)\}}" flags="">
<xsl:matching-substring>
<xsl:value-of select="$parameters/*[name() = regex-group(1)]"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
Et vous pouvez ensuite l’utiliser à loisir pour constituer vos chaînes de caractères :
<xsl:variable name="title"
select="if (field[@name='g_title'] != '') then field[@name='g_title'] else field[@name='g_pathComponent'][1]"/>
<xsl:variable name="description" select="if (field[@name='g_description'] != '') then field[@name='g_description'] else $title"/>
<xsl:variable name="summary" select="if (field[@name='g_summary'] != '') then field[@name='g_summary'] else $title"/>
<xsl:call-template name="template">
<xsl:with-param name="parameters">
<title>
<xsl:value-of select="$title"/>
</title>
<description>
<xsl:value-of select="$description"/>
</description>
<alttext>
<xsl:value-of select="$summary"/>
</alttext>
<gallery-title>
<xsl:value-of select="field[@name='g_pathComponent'][2]"/>
</gallery-title>
<filename>
<xsl:value-of select="field[@name='g_pathComponent'][1]"/>
</filename>
<sort-order>
<xsl:value-of select="position()"/>
</sort-order>
</xsl:with-param>
<xsl:with-param name="template"><![CDATA[update
wp_ngg_gallery g,
wp_ngg_pictures p
set
p.image_slug = "${title}",
p.description = "${description}",
p.alttext = "${alttext}",
p.sortorder = ${sort-order}
where
p.galleryid = g.gid
and g.title = "${gallery-title}"
and p.filename = "${filename}";
]]></xsl:with-param>
</xsl:call-template>
Simple et efficace, non?