Recherche de texte CDATA multiligne dans un tas de fichiers XML (éventuellement avec grep)

2

J'ai plusieurs milliers de fichiers XML (bien formés) du modèle suivant:

<?xml version="1.0" ?>
<queries>
  <statement name="foobar">
    <body><![CDATA[
      Several lines
      worth of
      text goes
      in here 
    ]]></body>
  </statement>
  <statement name="whatever">
    [... snip ...]
  </statement>
</queries>

Je dois obtenir une liste de ces déclarations pour lesquelles le contenu textuel du corps couvre plus de 10 lignes. À part écrire un script python à cet effet, existe-t-il un moyen simple d’utiliser grep ou d’autres outils standard pour examiner chaque fichier et renvoyer les instructions qui couvrent plusieurs lignes? À tout le moins, je serais heureux avec quelque chose qui renverrait une liste de noms de fichiers pour lesquels il existe une telle déclaration.

Fred
la source

Réponses:

2

À part l’utilisation d’une vraie bibliothèque XML et / ou de awk / perl / python / ruby, c’est assez proche de ce que vous voulez (si je vous ai bien compris) en utilisant simplement les commandes bash courantes.

Veuillez noter que ceci est vraiment spécifique aux fichiers xml utilisés et ne devrait pas être encouragé comme un analyseur / séparateur xml à usage général.

Vous aurez besoin du répertoire de sortie pour les fichiers fractionnés. J'ai utilisé / tmp / out pour cet exemple:

mkdir -p /tmp/out 

Vous devrez nettoyer /tmp/outavant chaque course. Sinon, vous obtiendrez des résultats qui n'ont pas de sens.

cat /path_to_xml_files/*.xml | \
egrep -v '<?xml version="1.0" \?>|<queries>|</queries>' | \
csplit -q -z - '/statement name/' '{*}' --prefix=/tmp/out/splitout- && \
for x in /tmp/out/splitout-* ; do \
[[ $(wc -l "$x"|cut -d" " -f 1) -gt 10 ]] && \
echo "$x" && \
cat "$x" ; \
done
  1. chat les fichiers XML
  2. Utilisez egrep pour supprimer les lignes indésirables
  3. diviser l'entrée en plusieurs fichiers en fonction de votre exemple de 'nom d'instruction'
  4. résultats de la boucle
  5. compter le nombre de lignes pour chaque fichier et exiger qu'il soit supérieur à 10
  6. nom de fichier de sortie d'impression
  7. imprimer les lignes de sortie

Comme je l'ai dit, il ne s'agit pas d'un séparateur XML général, mais doit être traité comme un exemple de commandes shell différentes.

Remarque: '\'-sign suivi de saut de ligne signifie que la ligne continue sans sauts de ligne. Cela facilite simplement la lecture.

Manwe
la source
1

Je ne peux faire que Ruby, avec la nokogirigemme installée. Je ne pense pas que l'utilisation de grep serait aussi simple que cela, mais peut-être que quelqu'un a une meilleure solution. La syntaxe est la suivante:

ruby scriptname.rb <directory> <number-of-lines>

Donc, par exemple:

ruby find.rb . 10

Ceci listera tous les .xmldocuments qui

  • contenir statements
  • avec un CDATAtexte
  • c'est dans body
  • qui a plus que des <number-of-lines>lignes de texte (>, pas ≥)

Il n'y a pas d'exception de manipulation cependant.


require 'nokogiri'
dir, lines = ARGV
@result = []
Dir.glob("#{dir}/*.xml") do |entry|
  Nokogiri::XML(File.open(entry)).xpath("//statement/body").each { |b| (@result << entry and break) if b.text.lines.count > (2+lines.to_i) }
end
puts @result
slhck
la source