Traitement d'un fichier xml avec awk/grep/sed

Traitement d'un fichier xml avec awk/grep/sed - Codes et scripts - Linux et OS Alternatifs

Marsh Posté le 08-08-2007 à 17:50:28    

Bonjour, j'ai un fichier xml composé de la façon suivante (c'est un exemple simplifié du fichier) :
 
<list id="list1">
<element id="1" another_attribute1="bla">
....
</element>
<element id="2" another_attribute1="bla">
....
</element>
....
</list>
<list id="list1">
<element id="3" another_attribute1="bla">
...
</element>
<element id="4" another_attribute1="bla">
....
</element>
....
</list>
 
et je souhaiterais pouvoir récupérer la valeur de chaque id pour une "list" donnée dans un script shell (bash/ksh...).
 
Je souhaiterais donc que le script me retourne pour la list : list1
1
2
 
Les id des listes je les connais et je peux donc les passer en paramètres.
 
J'essaye en vain de récupérer les valeurs avec sed/awk mais sans succés...
 
J'ai essayé de cette façon (je n'ai pas inclus le choix de la liste volontairement car je cherche à récupérer les valeurs des id en priorité, je ciblerais sur une list en particulier après) :
 
cat fichier.xml | grep "<element" | awk 'NF > 0 { for (i=1;i<=NF;i++) { if ( $i ~ /^[id]/ ) { print $i } } }'
 
ce qui me retourne :
 
id="1"
id="2">
 
(le ">" apparait quand l'attribut "id" se situe à la fin de la ligne)
 
Je ne sais pas trop comment aller plus loin...
 
Si quelqu'un avait une solution et/ou connaîtrait un outil (non graphique !) pour lire des fichiers XML ça serait sympa.
 
Merci d'avance.
 
Bye

Reply

Marsh Posté le 08-08-2007 à 17:50:28   

Reply

Marsh Posté le 08-08-2007 à 20:14:40    

Tu peux pas utiliser un peu de xslt :o ?

 

genre toto.xml :

<?xml version="1.0" encoding="utf-8" ?>
<lists>
    <list id="list1">
        <element id="1" another_attribute1="bla">
        </element>
        <element id="2" another_attribute1="bla">
        </element>
    </list>

 

   <list id="list2">
        <element id="3" another_attribute1="bla">
        </element>
        <element id="4" another_attribute1="bla">
        </element>
    </list>
</lists>

 


genre toto.xsl

<?xml version="1.0" encoding="utf-8" ?>

 

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml">

 

   <xsl:output method="text" encoding="utf-8"/>

 

   <!--
        on peut passer le nom de la liste en argument du processeur
        xslt
    -->
    <xsl:param name="toto" select='42'/>

 


    <!-- ce qu'on fait quand on match la "root" du document -->
    <xsl:template match="/">

 

       <!--
             on appelle la méthode qui match les <list>
             ayant l'id $toto
        -->
        <xsl:apply-templates select="lists/list[@id = $toto]"/>
    </xsl:template>

 


    <!-- quand on match un <list> on affiche les id des <element> -->
    <xsl:template match="list">
        <xsl:apply-templates select=".//element/@id"/>
    </xsl:template>

 

   
    <!-- l'affichage en question, avec un peu de décoration -->
    <xsl:template match="element/@id">
        J'ai trouvé : <xsl:value-of select="."/> et c'est cool.
    </xsl:template>

  

</xsl:stylesheet>

 


Et on appelle le tout en console avec un processeur xslt (ici xsltproc) :

xsltproc --stringparam toto "list1" toto.xsl toto.xml

   

Sinon on peut aussi le faire en shell :

Code :
  1. #!/bin/bash
  2. ID=$1
  3. exec 3< toto.xml
  4. while read line; do
  5.     if echo "$line" | grep -q ".*<list id=\""$ID"\">"; then
  6.         read line <&3
  7.         while ! echo "$line" | grep -q ".*<list id=.*>"; do
  8.             if echo "$line" | grep -q '.*<element id="[^"]*".*>'; then
  9.                 echo "$line" | sed -e 's_.*<element id="\([^"]*\)".*_\1_'
  10.             fi
  11.             read line <&3 || exit # end of file
  12.         done<&3
  13.         break
  14.     fi
  15. done <&3
 

Mais bon là c'est vraiment du ligne par ligne, si à un moment t'as une balise sur plusieurs lignes genre :

Code :
  1. <toto id="42"
  2.         foo="bar">


tout s'écroule :o


Message édité par Xavier_OM le 09-10-2007 à 18:50:53

---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
Reply

Marsh Posté le 09-08-2007 à 10:47:49    

Merci beaucoup, je vais regarder ça de plus près  ;)

Reply

Marsh Posté le 09-08-2007 à 22:22:13    


Le parseur le plus adapté est bien sûr "xslt" mais avec "awk" ça peut le faire aussi  :)  
Important, la double-quote défini le caractère  FS (File Separator) :
 
 

Code :
  1. ArgList=$1
  2. awk -F"\"" -v ArgList=$ArgList '
  3. BEGIN {
  4. Toplist_id=0
  5. TotElem=0
  6. }
  7. {
  8. if ($1 == "<list id=" ) {
  9.  if (Toplist_id == 1) {
  10.   exit
  11.  }
  12.  if ($2 == ArgList) {
  13.   print "* liste sélectionnée : "ArgList
  14.   Toplist_id=1
  15.  }
  16.  next
  17. }
  18. if ($1 == "<element id=" && Toplist_id == 1) {
  19.  TotElem++
  20.  print "* "$2
  21. }
  22. }
  23. END {
  24. if (Toplist_id == 0) {
  25.  print "*** liste "ArgList" non trouvée !!!!"
  26.  exit 1
  27. }
  28. if (TotElem == 0) {
  29.  print "*** Aucun élément trouvé dans liste "ArgList" !!!!"
  30.  exit 1
  31. }
  32. } ' fichier.xml


 
Résultat :
 
 
$ script list1
* liste sélectionnée : list1
* 1
* 2
 
 
 
 

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed