Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Document already has a root node" while using Builder #646

Closed
yokolet opened this issue Mar 31, 2012 · 4 comments
Closed

"Document already has a root node" while using Builder #646

yokolet opened this issue Mar 31, 2012 · 4 comments

Comments

@yokolet
Copy link
Member

yokolet commented Mar 31, 2012

This bug was found while investigating issue #641

require 'rubygems'
require 'nokogiri'

builder = Nokogiri::XML::Builder.new do |xml|
  0.upto(81900) do
    xml.text "test"
  end
end

raised:

RuntimeError: Document already has a root node
   add_child at /Users/yoko/Documents/workspace/Ranunculus/lib/nokogiri/xml/document.rb:212
     parent= at /Users/yoko/Documents/workspace/Ranunculus/lib/nokogiri/xml/node.rb:549
      insert at /Users/yoko/Documents/workspace/Ranunculus/lib/nokogiri/xml/builder.rb:371
        text at /Users/yoko/Documents/workspace/Ranunculus/lib/nokogiri/xml/builder.rb:302
    __file__ at ../Canna/src/snippet/issue641.rb:6
        upto at org/jruby/RubyInteger.java:139
    __file__ at ../Canna/src/snippet/issue641.rb:5
  initialize at /Users/yoko/Documents/workspace/Ranunculus/lib/nokogiri/xml/builder.rb:293
      (root) at ../Canna/src/snippet/issue641.rb:4
@yokolet
Copy link
Member Author

yokolet commented Apr 1, 2012

By investigation, JRuby might be wrong with block processing.

I changed the test as in below and added some puts statement in node.rb/builder.rb. This is becasuse there's no line to be a good breakpoint in Java code.

require 'rubygems'
require 'nokogiri'

builder = Nokogiri::XML::Builder.new do |xml|
  0.upto(3) do |i|
    xml.text "test" + i.to_s
  end
end

libxml version create:

<?xml version="1.0"?>
test0test1test2

while JRuby created:

<?xml version="1.0"?>
<text>test0</text>

then raised an error.

@yokolet
Copy link
Member Author

yokolet commented Apr 1, 2012

Oh, well, comment helps.

I found this in XmlNode.java

        /*
         * This is a bit of a hack.  C-Nokogiri allows adding a bare
         * text node as the root element.  Java (and XML spec?) does
         * not.  So we wrap the text node in an element.
         */

This case is the one. So, post processing is needed.

@msavy
Copy link

msavy commented Apr 2, 2012

I get this issue when using standard MRI/YARV. Any other random document I read in responds normally to #root (and not as if you're trying to assign), just seems to be builder as you've identified.

Code

require 'rubygems'
require 'nokogiri'

document = Nokogiri::XML::Builder.new{ something("other") { blah("fleg") } }

puts document.to_xml
document.root

Error

<?xml version="1.0"?>
<something>other<blah>fleg</blah></something>
/Users/msavy/.rvm/gems/ruby-1.9.3-p125/gems/nokogiri-1.5.0/lib/nokogiri/xml/document.rb:198:in `add_child': Document already has a root node (RuntimeError)
from /Users/msavy/.rvm/gems/ruby-1.9.3-p125/gems/nokogiri-1.5.0/lib/nokogiri/xml/node.rb:539:in `parent='
from /Users/msavy/.rvm/gems/ruby-1.9.3-p125/gems/nokogiri-1.5.0/lib/nokogiri/xml/builder.rb:365:in `insert'
from /Users/msavy/.rvm/gems/ruby-1.9.3-p125/gems/nokogiri-1.5.0/lib/nokogiri/xml/builder.rb:357:in `method_missing'
from example.rb:7:in `<main>'

Nokogiri (1.5.0)

---
warnings: []
nokogiri: 1.5.0
ruby:
  version: 1.9.3
  platform: x86_64-darwin10.8.0
  description: ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin10.8.0]
  engine: ruby
libxml:
  binding: extension
  compiled: 2.7.3
  loaded: 2.7.3

(breaks on 1.8.7 too)

@flavorjones
Copy link
Member

@msavy - you're seeing something very different than this issue was opened to address; and it's not a bug.

The variable you've named document in your snippet is not, in fact, a Nokogiri::XML::Document -- it's a Nokogiri::XML::Builder.

See http://nokogiri.org/Nokogiri/XML/Builder.html for supporting documentation, but Builder understands #to_xml and that's about it. Nearly any other method you call on it will be routed to #method_missing and cause the creation of an XML node. That's how Builder works its magic.

If you call #root on a bare Builder object, that act is interpreted as wanting to create an XML node <root /> under the root node. If you've already got a root node, then that's going to create an ill-formed document and raise the error you see above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants