2009-11-20 4 views
0

J'ai une chaîne XML simple, qui est plus ou moins toujours la même. Je préfère éviter d'utiliser un analyseur XML pour un si petit bout de code, et je pense que Regexp pourrait aider.Ruby Regexp pour extraire des éléments spécifiques dans une chaîne XML

La chaîne XML ressemble à:

<?xml version="1.0"?> 
<methodCall> 
    <methodName>weblogUpdates.extendedPing</methodName> 
    <params> 
    <param> 
     <value>Official Google Blog</value> 
    </param> 
    <param> 
     <value>http://googleblog.blogspot.com/</value> 
    </param> 
    <param> 
     <value>http://googleblog.blogspot.com/</value> 
    </param> 
    <param> 
     <value>http://googleblog.blogspot.com/atom.xml</value> 
    </param> 
    </params> 
</methodCall> 

Je veux extraire les valeurs de chaque param (et maintenir l'ordre).

je suis venu avec /<value>(.*)<\/value>/xi mais juste macthes la première valeur:/

Répondre

3

Parsing XML with Ruby is trivial, s'il vous plaît ne pas essayer d'analyser XML avec une expression régulière - il est notoirement difficile et sujette aux erreurs.

Bien qu'il soit tentant d'essayer d'utiliser une expression régulière, ne le faites pas. Peu importe combien vous essayez d'écraser ce clou avec le tournevis, il ne fonctionnera pas comme un marteau - s'il vous plaît utiliser l'un des nombreux marteaux merveilleux à votre disposition.

+1

S'il vous plaît, arrêtez de diffuser ce mème: analyser XML avec une expression régulière n'est pas "notoirement difficile et sujet aux erreurs", c'est simplement impossible. Et pas impossible dans le sens de "impossible à obtenir", mais mathématiquement impossible.En fait, à peu près tous les étudiants de CS sur la planète entière auront à un moment de leur carrière prouvé cette impossibilité dans une tâche de devoirs ou autre. –

+2

@ Jörg - J'ai peur que vous et moi parlions de deux choses très différentes. L'impossibilité mathématique est très différente de l'impossibilité réelle (faute d'une meilleure phrase). Est-il impossible d'utiliser des expressions régulières sur XML? Non, bien sûr que non - il est tout à fait possible d'utiliser des expressions régulières pour pirater une solution qui fonctionnera la plupart du temps. Je comprends votre point de vue (et je suis d'accord avec vous en principe), mais cela n'a pas beaucoup d'influence sur une discussion pratique comme celle-ci. –

1

Normalement, vous devriez utiliser un analyseur XML, mais je pense toujours que c'est un peu exagéré.

Si vous êtes comme moi, je le ferais comme ceci:

x = File.new("test.xml", "r").read 
puts x.scan(/<value>(.*)<\/value>/) 

qui se traduit par:

Official Google Blog 
http://googleblog.blogspot.com/ 
http://googleblog.blogspot.com/ 
http://googleblog.blogspot.com/atom.xml 

Si vous voulez faire une boucle sur chaque valeur, vous pouvez le faire comme ça :

x.scan(/<value>(.*)<\/value>/) do |x| 
    puts x 
end 
+2

L'analyse XML via regex est une mauvaise pratique et une source d'erreurs. Voir la réponse: http://stackoverflow.com/a/1768230/99266 –

+0

Enfin une vraie réponse à la question pour ceux d'entre nous qui peuvent faire confiance à notre entrée et ne pas utiliser le gros marteau LOL – rogerdpack

1

comme un simple commentaire de côté, pour cette application spécifique, il peut se sentir Nokogiri difficile, mais l'apprentissage ou libxml qu'Il Si vous prenez une décision à propos de l'analyse XML plus complexe sur toute la ligne. En outre, analyser XML dans Ruby est vraiment trivial de nos jours et le faire au moins rendra facile l'expansion à une méthode non triviale lorsque votre client demande finalement que vous fassiez quelque chose ridiculement hors de portée qui implique l'analyse XML complète. :)

Pour d'autres cadres et de la technologie, je ne recommanderais probablement pas un tel investissement, mais Nokogiri est indolore. Et si vous avez juste envie de jouer, vous pouvez essayer Hpricot et obtenir votre dose de _why pour la journée (RIP).

+0

+1 pour [Nokogiri] (http : //nokogiri.org). Je le recommande sur Hpricot; Les accesseurs sont très similaires, mais Nokogiri est plus robuste. –

0

Je ne vois aucune raison d'utiliser une regex au lieu d'un vrai parser. La simplicité d'utilisation est une excuse horrible qui ne se révèle pas être vrai:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0"?> 
<methodCall> 
    <methodName>weblogUpdates.extendedPing</methodName> 
    <params> 
    <param> 
     <value>Official Google Blog</value> 
    </param> 
    <param> 
     <value>http://googleblog.blogspot.com/</value> 
    </param> 
    <param> 
     <value>http://googleblog.blogspot.com/</value> 
    </param> 
    <param> 
     <value>http://googleblog.blogspot.com/atom.xml</value> 
    </param> 
    </params> 
</methodCall> 
EOT 

puts doc.search('value').map(&:text) 

Course à sorties:

Official Google Blog 
http://googleblog.blogspot.com/ 
http://googleblog.blogspot.com/ 
http://googleblog.blogspot.com/atom.xml 

S'il est nécessaire d'être plus précis, percez vers le bas avec un CSS plus spécifique chemin:

doc.search('param value') 

en utilisant une expression régulière, comme %r(<value>(.*)</value>) sera « Splode si le texte contenu contient "</value>" et piégeant ces situations plonge un r très profond trou abbit.

Questions connexes