Handling exceptions in Builder::XmlMarkup
I was wondering what a good practice is for handling errors when generating large XML feeds using Ruby's XML builder? The problem I have is that I am writing millions of records to an XML file, and due to data quality, some may fail.
However, I don't want the builder to terminate because of a single failing record. Here's a snippet that illustrates the problem:
xml = Builder::XmlMarkup.new
xml.outer do
begin
xml.inner do
xml.text "content"
raise "your hands"
end
rescue
puts "how should this be handled?"
end
end
This will output the following XML:
<outer&g开发者_如何学编程t;<inner><text>content</text></outer>
which is invalid, since <inner>
is never closed.
How would I do this properly?
It's not ideal, but you can manually append close tags (or anything else, really) to an XmlBuilder instance using <<. It sounds like you're looking for something like this:
xml = Builder::XmlMarkup.new
xml.outer do
begin
xml.inner do
xml.text "content"
raise "your hands"
end
rescue
xml << "</inner>"
end
end
Because the rescue inserts the </inner>
tag, you'll get an output like this:
"<outer><inner><text>content</text></inner></outer>"
UPDATE
Ah, based on your comment, then, you're looking for something using nested XmlMarkups. Try this:
outside_xml = Builder::XmlMarkup.new
outside_xml.outer do
begin
# Declare a string to use as a buffer
buffer = ''
# Create a separate XmlMarkup builder that writes to the buffer
inside_xml = Builder::XmlMarkup.new(target: buffer)
inside_xml.inner do
inside_xml.text "content"
raise "your hands"
end
rescue
# Clear the buffer on an error
buffer = ''
end
# Write the finished buffer inside the outside XmlMarkup builder
outside_xml << buffer
end
This is a bit trickier, since it's using two separate XML builders. There's essentially no way to roll back a tag in XmlMarkup. Instead, we use a separate XmlMarkup instance for the inner content and manually give it to the outer builder -- because we're using a target for the inner builder, we can adjust the contents of the target from outside the XmlBuilder before we pass it on.
So, if you run this new example with the exception, you'll get:
<outer></outer>
And if you run it with the exception commented out, you'll get:
<outer><inner><text>content</text></inner></outer>
Is this what you're looking for?
精彩评论