Forum Programmation.autre XML : ajouter un nouveau nœud autour d'un nœud existant

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
21
sept.
2013

Bonjour à tous,

Je suis en train de faire un script pour éditer automatiquement un grand nombre de fichiers HTML comme du XML avec xmllint et xmlstarlet pour extraire le contenu qui m'intéresse, les mettre en forme grâce à une CSS de mon propre cru, et imprimer le tout de manière lisible pour être lu devant une assemblée.

J'aimerais savoir s'il existe un outil et/ou une commande permettant simplement d'ajouter un nœud autour d'un nœud existant, de manière à ce que ce dernier devienne le fils de ce nouveau nœud. Plus précisément, j'ai actuellement ceci :

<table>
  <tr><td>Donnée 1</td></tr>
  <tr><td>Donnée 2</td></tr>
  <tr><td>Donnée 3</td></tr>
  <tr><td>Donnée 4</td></tr>
  <tr><td>Donnée 5</td></tr>
  <tr class="pieddetable"><td>Bas de table</td></tr>
</table>

et je voudrais obtenir ceci :

<table>
  <tr><td>Donnée 1</td></tr>
  <tr><td>Donnée 2</td></tr>
  <tr><td>Donnée 3</td></tr>
  <tr><td>Donnée 4</td></tr>
  <tr><td>Donnée 5</td></tr>
  <tfoot>
    <tr class="pieddetable"><td>Bas de table</td></tr>
  </tfoot>
</table>

J'arrive facilement à extraire le contenu des tables grâce à des chemins XPath et même à référencer leurs parents mais je ne sais pas s'il est possible d'auto-référencer un nœud lorsque l'on précise le chemin de destination.

Le problème est que j'ai potentiellement plusieurs tables consécutives au sein du même document. Quand il n'y en a qu'une seule, je peux créer un nœuds « tfoot » dans « //tr[@class='pieddetable']/.. » puis déplacer « //tr[@class='pieddetable'] » vers « //tfoot » mais quand il y en a plusieurs, il n'y bien sûr plus de relation pair à pair entre les deux balises.

Merci à tous pour votre aide.

  • # XSLT

    Posté par  . Évalué à 4. Dernière modification le 21 septembre 2013 à 22:42.

    XSLT est fait pour ça.
    Voici la «feuille de style» XSL qui permet d'obtenir ce résultat:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:template match="tr[@class='pieddetable']">
      <tfoot>
       <xsl:copy>
        <xsl:apply-templates select="@*" />
        <xsl:apply-templates />
       </xsl:copy>
      </tfoot>
     </xsl:template>
     <xsl:template match="*|@*">
      <xsl:copy>
       <xsl:apply-templates select="@*" />
       <xsl:apply-templates />
      </xsl:copy>
     </xsl:template>
    </xsl:stylesheet>

    (note que je suppose ici que ton document d'origine n'a pas de namespace, sinon il faut en tenir compte)
    Ensuite tu peux appliquer cet XSL à tes fichiers avec xmlstarlet ou xsltproc.
    C'est un peu plus compliqué si tu peux avoir plusieurs tr dans une même table que tu veux regrouper dans un unique tfoot.

    • [^] # Re: XSLT

      Posté par  . Évalué à 2.

      Merci beaucoup pour cet exemple ! Je n'avais pas pensé à faire une transformée XSLT et, à dire vrai, je ne pensais pas en avoir besoin initialement pour si peu.

      Cela dit, j'ai eu d'autres besoins entre temps, comme déplacer un titre H1 dans l'entête s'il existe et le répéter par la suite. Tout ceci m'a conduit à faire usage des options -i (insert), -s (subnode), -m (move) et -r (rename) de xmlstarlet pour créer les nœuds aux bons endroits et pouvoir déplacer facilement ceux qui avaient besoin de l'être.

      Merci encore pour ton aide.

      • [^] # Re: XSLT

        Posté par  (site web personnel, Mastodon) . Évalué à 3.

        Merci beaucoup pour cet exemple ! Je n'avais pas pensé à faire une transformée XSLT et, à dire vrai, je ne pensais pas en avoir besoin initialement pour si peu.

        XSLT est fait pour le cas que tu décris.

        • [^] # Re: XSLT

          Posté par  (site web personnel) . Évalué à 3.

          Pas tout à fait. XSLT est mal fait, pas des êtres inhumains, pour des être inhumains, pour traiter du XML. Les humains normaux galèrent avec, eux.

          • [^] # Re: XSLT

            Posté par  . Évalué à 2.

            j'ai relu 3 fois la phrase mais j'ai pas compris … alors je pense qu'il y a une faute :
            pa s r des être inhumains

            Du coup je suis assez d'accord …

            • [^] # Re: XSLT

              Posté par  . Évalué à 3.

              Xml is like violence - if it doesn't work, use more!

              Il ne faut pas décorner les boeufs avant d'avoir semé le vent

  • # Traitement par lignes

    Posté par  (site web personnel) . Évalué à 4.

    Sinon, tu peux utiliser xmlstarlet pyx, ou xml2 pour transformer ton XML en une série de lignes que tu pourras traiter avec sed.

    Par exemple :

    $ xmlstarlet pyx | sed -e '/^(tr$/i\
    (tfoot
    /^)tr$/a
    )tfoot
    ' | xmlstarlet p2x

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.