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

JRuby NAMESPACE_ERR when root node has a namespace prefix #217

Closed
yvesll opened this issue Jul 12, 2023 · 3 comments · Fixed by #222
Closed

JRuby NAMESPACE_ERR when root node has a namespace prefix #217

yvesll opened this issue Jul 12, 2023 · 3 comments · Fixed by #222

Comments

@yvesll
Copy link

yvesll commented Jul 12, 2023

Environment

JRuby: 9.4.3.0
nokogiri (1.15.3 java)
nokogiri-happymapper (0.9.0)

Description

My generated xml loooks like:

<?xml version="1.0" encoding="UTF-8"?>
<namespace:demo xmlns:namespace=URL>
  ......
<namespace:demo>

Ruby code:

require 'happymapper'

class Demo
  include HappyMapper

  register_namespace 'namespace', 'URL'

  tag 'namespace:demo'
end

puts Demo.new.to_xml

It works fine with MRI Ruby, but within JRuby, it reports following errors:

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:330
                   rbNew at nokogiri/XmlNode.java:277
                    call at nokogiri/XmlNode$INVOKER$s$0$0$rbNew.gen:-1
            cacheAndCall at org/jruby/runtime/callsite/CachingCallSite.java:446
                    call at org/jruby/runtime/callsite/CachingCallSite.java:92
               interpret at org/jruby/ir/instructions/CallBase.java:561
             processCall at org/jruby/ir/interpreter/InterpreterEngine.java:367
               interpret at org/jruby/ir/interpreter/StartupInterpreterEngine.java:66
        INTERPRET_METHOD at org/jruby/internal/runtime/methods/MixedModeIRMethod.java:128
                    call at org/jruby/internal/runtime/methods/MixedModeIRMethod.java:115
            cacheAndCall at org/jruby/runtime/callsite/CachingCallSite.java:446
                    call at org/jruby/runtime/callsite/CachingCallSite.java:92
                callIter at org/jruby/runtime/callsite/CachingCallSite.java:103
               interpret at org/jruby/ir/instructions/CallBase.java:558
             processCall at org/jruby/ir/interpreter/InterpreterEngine.java:367
               interpret at org/jruby/ir/interpreter/StartupInterpreterEngine.java:66
        INTERPRET_METHOD at org/jruby/internal/runtime/methods/MixedModeIRMethod.java:128
                    call at org/jruby/internal/runtime/methods/MixedModeIRMethod.java:115
                    call at org/jruby/runtime/Helpers.java:600
       callMethodMissing at org/jruby/runtime/Helpers.java:117
  finvokeWithRefinements at org/jruby/RubyClass.java:520
                    send at org/jruby/RubyBasicObject.java:1703
                    send at org/jruby/RubyKernel.java:2355
                    call at org/jruby/RubyKernel$INVOKER$s$send.gen:-1
            cacheAndCall at org/jruby/runtime/callsite/CachingCallSite.java:446
                    call at org/jruby/runtime/callsite/CachingCallSite.java:92
                callIter at org/jruby/runtime/callsite/CachingCallSite.java:103
               interpret at org/jruby/ir/instructions/CallBase.java:558
             processCall at org/jruby/ir/interpreter/InterpreterEngine.java:367
               interpret at org/jruby/ir/interpreter/StartupInterpreterEngine.java:66
               interpret at org/jruby/ir/interpreter/InterpreterEngine.java:76
        INTERPRET_METHOD at org/jruby/internal/runtime/methods/MixedModeIRMethod.java:164
                    call at org/jruby/internal/runtime/methods/MixedModeIRMethod.java:151
                    call at org/jruby/internal/runtime/methods/DynamicMethod.java:212
            cacheAndCall at org/jruby/runtime/callsite/CachingCallSite.java:456
                    call at org/jruby/runtime/callsite/CachingCallSite.java:195
     invokeOther5:to_xml at nokogiri.rb:11
             RUBY$script at nokogiri.rb:11
                     run at nokogiri.rb:-1
     invokeWithArguments at java/lang/invoke/MethodHandle.java:710
                    load at org/jruby/ir/Compiler.java:114
               runScript at org/jruby/Ruby.java:1276
             runNormally at org/jruby/Ruby.java:1193
             runNormally at org/jruby/Ruby.java:1175
             runNormally at org/jruby/Ruby.java:1211
             runFromMain at org/jruby/Ruby.java:989
           doRunFromMain at org/jruby/Main.java:398
             internalRun at org/jruby/Main.java:282
                     run at org/jruby/Main.java:227
                    main at org/jruby/Main.java:199

I guess that the user cannot send a node with a namespace before adding the definition of the namespace.
I applied a workaround in the to_xml method and it works:

def to_xml(builder = nil, default_namespace = nil, namespace_override = nil,
             tag_from_parent = nil)
    
    <code>

    root_tag = "#{tag_from_parent || self.class.tag_name}_"
    if root_tag.include?(':')
      namespace, tag = root_tag.split(':')
      namespace_name ||= namespace
      root_tag = tag
    end
    builder.send(root_tag, attributes) do |xml|

    <code>
end
@mvz
Copy link
Owner

mvz commented Jul 14, 2023

It seems this only works with MRI by accident. The way to specify a namespace for a Class' tag is with the namespace method. So the Demo class would look like this:

class Demo
  include HappyMapper

  register_namespace 'namespace', 'URL'

  tag 'demo'
  namespace 'namespace'
end

This version works with both MRI and JRuby.

I'm going to add a check to prevent tags that include : characters.

@yvesll
Copy link
Author

yvesll commented Jul 17, 2023

HI, @mvz, thanks for the explanation. But how can I setup to only add a namespace prefix for the tag 'demo' but not for child nodes?

@mvz
Copy link
Owner

mvz commented Jul 17, 2023

@yvesll coincidentally, someone else just asked the same question: #223. I'm going to investigate and answer it there.

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

Successfully merging a pull request may close this issue.

2 participants