2013-08-10 16 views
6

Mam ten xml:Nokogiri zrobić każdy węzeł, Ruby

<kapitel> 
     <nummer V="1"/> 
     <von_icd_code V="A00"/> 
     <bis_icd_code V="B99"/> 
     <bezeichnung V="Bestimmte infektiöse und parasitäre Krankheiten"/> 
     <gruppen_liste> 
     <gruppe> 
      <von_icd_code V="A00"/> 
      <bis_icd_code V="A09"/> 
      <bezeichnung V="Infektiöse Darmkrankheiten"/> 
      <diagnosen_liste> 
      <diagnose> 
       <icd_code V="A00.-"/> 
       <bezeichnung V="Cholera"/> 
       <abrechenbar V="n"/> 
       <krankheit_in_mitteleuropa_sehr_selten V="j"/> 
       <schlüsselnummer_mit_inhalt_belegt V="j"/> 
       <infektionsschutzgesetz_meldepflicht V="j"/> 
       <infektionsschutzgesetz_abrechnungsbesonderheit V="j"/> 

Jak widać mój pierwszy węzeł jest kapitel. Chciałbym zrobić coś takiego, jak kapitel .each do | f | aby nokgiri wyodrębnił węzły von_icd_code i bis_icd_code we właściwej kolejności. Mój kod:

require 'rubygems' 
    require 'nokogiri' 
    require 'open-uri' 

@doc = Nokogiri::XML(File.open("icd.xml")) 

    kapitel = @doc.css('kapitel') 
    kapitel.each do |f| 
    puts f.css('von_icd_code') 
    puts f.css('bis_icd_code') 
    end 

Problemem jest to, że nogiri nie EXTRAKT się „von_icd_code” oraz 'bis_icd_code w prawym Odry, zamiast najpierw wymienić wszystkie von_icd_code A potem „bis_icd_code”. Jak mogę wypróbować węzły w odpowiednim oderze?

I w moim wyjściu uzyskać:

<von_icd_code V="A00"/> 

Jak mogę dostać tylko treść V w tym przypadku A00

Dzięki!

Odpowiedz

5

Od bis_icd_code następująco każdy von_icd_code, oczywistym wyborem jest css's + obok przylega selektor rodzeństwa:

doc.css('von_icd_code').each do |icd| 
    puts icd['V'] 
    puts icd.at('+ bis_icd_code')['V'] 
end 
#=> A00 
#=> B99 
#=> A00 
#=> A09 
+0

To opiera się na 'bis_icd_code' zawsze pojawiającym się * po *' von_icd_code' w parach. Mogą to zrobić, ale nie ma na to dowodów. – Borodin

+0

Oczywiście istnieją dowody na to. Spójrz na przykład. – pguardiario

5

Możesz użyć metody Nokogiri traverse, która, dobrze, przemierza wszystkie węzły XML w sposób rekursywny.

Wasz przykład będzie wtedy wyglądać podobnie do tego:

names = %w(von_icd_code bis_icd_code) 
@doc.traverse {|node| p node['V'] if names.include? node.name} 

I wypisuje

"A00" 
"B99" 
"A00" 
"A09" 

Jest dużo porządnych rzeczy w Nokogiri::Node które pozwalają nam robić naprawdę fajne rzeczy z jeszcze najbardziej złożone pliki XML. Aby zobaczyć ich krótką listę, możesz spojrzeć na at this cheat sheet.

Powodzenia!

+0

Dzięki, masz jakieś idee, jak mogę rozwiązać mój pierwszy problem, tak, że węzły pojawiają się w prawym oder? –

+1

Już to robią, jeśli zmienimy kod z 'p node ['V']' na 'p node.name', będziemy mieli węzły we właściwej kolejności. –

+0

Przepraszam, ale otrzymuję tekst wyjściowy tekst icd_code ...! Mój kod: names =% w (von_icd_code bis_icd_code) @ doc.traverse {| node | p węzeł ['V'] jeśli names.include? puts node.name} –

2

Aktualizacja

Przepraszam, to nie działa z selektorów CSS. Zamiast tego użyj XPath. A co do drugiego pytania, do atrybutu V węzła node można uzyskać dostęp w Nokogiri przy użyciu node['V']. Podoba Ci się to

kapitel = @doc.xpath('//kapitel') 
kapitel.each do |f| 
    f.xpath('//von_icd_code | //bis_icd_code').each do |node| 
    puts node['V'] 
    end 
end 

wyjściu

A00 
B99 
A00 
A09 

Można to naprawić bez ekstrawagancji traverse pisząc

kapitel.each do |f| 
    puts f.css('von_icd_code, bis_icd_code') 
end 
+0

Mówisz, że to nie działa z selektorami css, to pokazuje, że tak. Wybierz stronę. – pguardiario

+0

@pguardiario: Aktualizacja przy użyciu XPath działa poprawnie. Oryginał, który używa CSS, iteruje przez wszystkie elementy 'von_icd_code', a następnie przez elementy' bis_ice_code'. – Borodin

Powiązane problemy