sparklemotion / nokogiri

Nokogiri (鋸) makes it easy and painless to work with XML and HTML from Ruby.
https://nokogiri.org/
MIT License
6.12k stars 900 forks source link

JRuby Builder throws namespace error when creating a node with a non-default namespace #1854

Open WoolenWang opened 5 years ago

WoolenWang commented 5 years ago

If you're having trouble installing Nokogiri ...

Have you tried following the installation tutorial?

What is the output of gem install?

What are the contents of the mkmf.log file?

What operating system are you using? win10 jruby9.1.13

If this isn't an installation issue ...

What problems are you experiencing?

NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.

What's the output from nokogiri -v? 1.10.0 (same problem with 1.9.1) Can you provide a self-contained script that reproduces what you're seeing? using gem AllureRubyAdaptorApi it use nokogiri

in the line : https://github.com/sparklemotion/nokogiri/blob/master/lib/nokogiri/xml/document.rb#L89

def create_element name, *args, &block
        elm = Nokogiri::XML::Element.new(name, self, &block)
        args.each do |arg|

get error just like Nokogiri::XML::Element.new('abc:def',self,&block)

the allure api gem usage is just like ::

https://github.com/allure-framework/allure-ruby-commons/blob/master/lib/allure-ruby-adaptor-api/builder.rb#L126

is that another way to create a xml node with name "ns2:test-suite"

flavorjones commented 5 years ago

Hi, thanks for asking this question.

I wrote the following script to reproduce what you're seeing:

#! /usr/bin/env ruby

require 'nokogiri'

builder = Nokogiri::XML::Builder.new do |xml|
  xml.send "ns2:test-suite", 'xmlns' => '', "xmlns:ns2" => "urn:model.allure.qatools.yandex.ru" do
    xml.send :name, "my name"
  end
end

puts builder.doc.to_xml

On CRuby (with libxml2), the output is:

<?xml version="1.0"?>
<ns2:test-suite xmlns="" xmlns:ns2="urn:model.allure.qatools.yandex.ru">
  <name>my name</name>
</ns2:test-suite>

On JRuby (with xerces), the result is an error:

Unhandled Java exception: org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
            setName at org/apache/xerces/dom/ElementNSImpl:-1
             <init> at org/apache/xerces/dom/ElementNSImpl:-1
    createElementNS at org/apache/xerces/dom/CoreDocumentImpl:-1
               init at nokogiri/XmlNode.java:340
              rbNew at nokogiri/XmlNode.java:298
...

Have I accurately reproduced what you're seeing?

flavorjones commented 5 years ago

Related content on the internet reveals what might be a workaround: https://gist.github.com/mudge/428455

so updating code to be:

builder = Nokogiri::XML::Builder.new do |xml|
  xml.send "test-suite", 'xmlns' => '' do
    xml.parent.namespace = xml.parent.add_namespace_definition "xmlns:ns2", "urn:model.allure.qatools.yandex.ru"
    xml.send :name, "my name"
  end
end

Nokogiri on JRuby now outputs:

<?xml version="1.0"?>
<xmlns:ns2:test-suite xmlns="" xmlns:xmlns:ns2="urn:model.allure.qatools.yandex.ru">
  <name>my name</name>
</xmlns:ns2:test-suite>

So if you need to work around this bug for now, you can.