Formattage de texte en XSLT 2.0

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?

Share and Enjoy:
  • Identi.ca
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • Add to favorites

Leave a Reply

Your email address will not be published. Required fields are marked *

Enter your OpenID as your website to log and skip name and email validation and moderation!