开发者

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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜