Suchen von mehrzeiligem CDATA-Text in einer Reihe von XML-Dateien (möglicherweise mit grep)

1

Ich habe mehrere tausend (wohlgeformte) XML-Dateien der folgenden Vorlage:

<?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>

Ich brauche eine Liste der Aussagen, deren Textinhalt sich über 10 Zeilen erstreckt. Gibt es eine einfache Möglichkeit, mit grep oder anderen Standardtools in jede Datei zu schauen und die Anweisungen zurückzugeben, die viele Zeilen umfassen, ohne ein Python-Skript zu schreiben? Zumindest würde ich mich über etwas freuen, das eine Liste von Dateinamen zurückgibt, für die es eine solche Aussage gibt.

Fred
quelle

Antworten:

2

Abgesehen von der Verwendung einer echten XML-Bibliothek und / oder awk / perl / python / ruby ​​entspricht dies ziemlich genau dem, was Sie wollen (wenn ich Sie richtig verstanden habe), indem Sie nur allgemeine Bash-Befehle verwenden.

Bitte beachten Sie, dass dies wirklich spezifisch für verwendete XML-Dateien ist und nicht als allgemeiner XML-Parser / Splitter empfohlen werden sollte.

Sie benötigen ein Ausgabeverzeichnis für die aufgeteilten Dateien. Ich habe / tmp / out für dieses Beispiel verwendet:

mkdir -p /tmp/out 

Sie müssen /tmp/outvor jedem Lauf reinigen . Andernfalls erhalten Sie Ergebnisse, die keinen Sinn ergeben.

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. Katze die XML-Dateien
  2. Verwenden Sie egrep, um unerwünschte Linien zu entfernen
  3. Eingabe auf mehrere Dateien aufteilen, basierend auf Ihrem Beispiel "Anweisungsname"
  4. Schleifenergebnisse
  5. Zählen Sie die Zeilen für jede Datei und fordern Sie mehr als 10
  6. Ausgabedateiname drucken
  7. Ausgabezeilen drucken

Wie ich bereits sagte, ist dies kein allgemeiner XML-Splitter, sondern ein Beispiel für verschiedene Shell-Befehle.

Hinweis: '\'-Zeichen gefolgt von Zeilenumbruch bedeutet, dass die Zeile ohne Zeilenumbrüche fortgesetzt wird. Dies erleichtert nur das Lesen.

Manwe
quelle
1

Ich kann nur Ruby machen, wenn der nokogiriGem installiert ist. Ich denke nicht, dass die Verwendung von grep hier so einfach ist, aber vielleicht hat jemand eine bessere Lösung. Die Syntax lautet:

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

Also zum Beispiel:

ruby find.rb . 10

Dies listet alle .xmlDokumente auf, die

  • enthalten statements
  • mit einem CDATAtext
  • das ist in body
  • die mehr als <number-of-lines>Textzeilen enthält (>, nicht ≥)

Es gibt jedoch keine Ausnahmebehandlung.


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
quelle