I wrote this little program:
require 'open-uri'
require 'nokogiri'
class Kapitel
attr_accessor :von, :bis, :bezeichnung
end
class SubKapitel
attr_accessor :von, :bis, :bezeichnung
end
def parse_file
doc = Nokogiri::XML(File.open("test.xml"))
parse_xml(doc)
end
def parse_xml(doc)
doc.root.elements.each do |node|
parse_kapitel(node)
end
end
def parse_kapitel(node)
if node.node_name.eql? 'nummer'
tmp_kapitel = Kapitel.new
end
if node.node_name.eql? 'gruppe'
tmp_kapitel = SubKapitel.new
end
tmp_kapitel.von = node['V'] if node.node_name.eql? 'von_icd_code'
tmp_kapitel.bis = node['V'] if node.node_name.eql? 'bis_icd_code'
end
puts parse_file
Using that, I parse this XML file:
<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"/>
But somehow I get this error:
test.rb:32:in `parse_kapitel': undefined method `von=' for nil:NilClass(NoMethodError)
I think the problem is that von-icd-code
appears twice in the XML document.
Can somebody help me to solve this problem?
require 'nokogiri'
doc = Nokogiri::XML(' <kapitel>
<nummer V="1"/>
<von_icd_code V="A00"/>
<bis_icd_code V="B99"/>
<bezeichnung V="Bestimmte infektise und parasitre Krankheiten"/>FFC3\U+FFA4re Krankheiten"/>
<gruppen_liste>
<gruppe>
<von_icd_code V="A00"/>
<bis_icd_code V="A09"/>
<bezeichnung V="Infektise Darmkrankheiten"/>krankheiten"/>
<diagnosen_liste>
<diagnose>
<icd_code V="A00.-"/>
<bezeichnung V="Cholera"/>
<abrechenbar V="n"/>')
doc.errors
Which outputs:
[
[0] #<Nokogiri::XML::SyntaxError: Premature end of data in tag diagnose line 12>,
[1] #<Nokogiri::XML::SyntaxError: Premature end of data in tag diagnosen_liste line 11>,
[2] #<Nokogiri::XML::SyntaxError: Premature end of data in tag gruppe line 7>,
[3] #<Nokogiri::XML::SyntaxError: Premature end of data in tag gruppen_liste line 6>,
[4] #<Nokogiri::XML::SyntaxError: Premature end of data in tag kapitel line 1>
]
If we look at what Nokogiri had to do to fix-up the XML:
puts doc.to_xml
We see that it added closing tags.
<?xml version="1.0"?>
<kapitel>
<nummer V="1"/>
<von_icd_code V="A00"/>
<bis_icd_code V="B99"/>
<bezeichnung V="Bestimmte infektise und parasitre Krankheiten"/>
<gruppen_liste>
<gruppe>
<von_icd_code V="A00"/>
<bis_icd_code V="A09"/>
<bezeichnung V="Infektise Darmkrankheiten"/>
<diagnosen_liste>
<diagnose>
<icd_code V="A00.-"/>
<bezeichnung V="Cholera"/>
<abrechenbar V="n"/></diagnose></diagnosen_liste></gruppe></gruppen_liste></kapitel>
It was able to do so correctly for this XML, but in XML that is malformed, or has more complicated data it might not do as well. And, at that point, any subsequent work on the resulting DOM would be suspect.
Inside the method
def parse_kapitel(node)
if node.node_name.eql? 'nummer'
tmp_kapitel = Kapitel.new
end
if node.node_name.eql? 'gruppe'
tmp_kapitel = SubKapitel.new
end
tmp_kapitel.von = node['V'] if node.node_name.eql? 'von_icd_code'
tmp_kapitel.bis = node['V'] if node.node_name.eql? 'bis_icd_code'
end
The error undefined method 'von=' for nil:NilClass(NoMethodError) means at that time node
name is 'von_icd_code'
, not the 'nummer'
. That's why the if node.node_name.eql? 'nummer'
evaluated as false
. But in Ruby local variables are created at parse time,whenever any such assignment statement encountered like, tmp_kapitel = Kapitel.new
.Now due to flase
evluation of the if node.node_name.eql? 'nummer'
,as I said earlier,tmp_kapitel
local variable holds nil
,not the object of Kapitel.new
. And NilClass
doesn't have any method called #von
,so the legitimate error thrown to you.