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

Error in mapping_rule.rb when running .to_xml with an element with same name in attribute and element #217

Closed
kwkwan opened this issue Dec 19, 2024 · 4 comments · Fixed by #250
Assignees
Labels
bug Something isn't working

Comments

@kwkwan
Copy link
Contributor

kwkwan commented Dec 19, 2024

Refer to https://github.com/lutaml/xmi/blob/main/spec/fixtures/ISO%206709%20Edition%202.xml, some node like ownedComment may have annotatedElement as an attribute or as an element.

i.e.

test1 = <<~TEST1
<ownedComment>
  <annotatedElement xmi:idref="ABC"/>
</ownedComment>
TEST1

or

test2 = <<~TEST2
<ownedComment annotatedElement="test2">
</ownedComment>
TEST2

Suppose we have class definitions like:

require "nokogiri"
require "lutaml/model"
require "lutaml/model/xml_adapter/nokogiri_adapter"

Lutaml::Model::Config.configure do |config|
  config.xml_adapter = Lutaml::Model::XmlAdapter::NokogiriAdapter
end

class AnnotatedElement < Lutaml::Model::Serializable
  attribute :idref, :string

  xml do
    root "annotatedElement"
    map_attribute "idref", to: :idref, namespace: "http://www.omg.org/spec/XMI/20131001", prefix: "xmi"
  end
end

class OwnedComment < Lutaml::Model::Serializable
  attribute :annotated_attribute, :string
  attribute :annotated_element, AnnotatedElement

  xml do
    root "ownedComment"
    map_attribute "annotatedElement", to: :annotated_attribute
    map_element "annotatedElement", to: :annotated_element, prefix: nil, namespace: nil
  end
end

When we run OwnedComment.from_xml like:

t2 = OwnedComment.from_xml(test2)
t2.to_xml

Error will occur like the following output:

~/src/lutaml/lutaml-model/lib/lutaml/model/mapping_rule.rb:45:in `public_send': undefined method `idref' for "test2":String (NoMethodError)
                                     
          model.public_send(to)      
               ^^^^^^^^^^^^
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/mapping_rule.rb:45:in `to_value_for'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:347:in `block in build_attributes'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:339:in `each'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:339:in `each_with_object'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:339:in `build_attributes'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:189:in `build_unordered_element'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:124:in `build_element'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:53:in `handle_nested_elements'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:149:in `add_to_xml'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:225:in `block (2 levels) in build_unordered_element'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:213:in `each'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/xml_document.rb:213:in `block in build_unordered_element'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/builder/nokogiri.rb:47:in `block in create_and_add_element'
	from ~/.rbenv/versions/3.1.5/lib/ruby/gems/3.1.0/gems/nokogiri-1.17.2-arm64-darwin/lib/nokogiri/xml/builder.rb:433:in `insert'
	from ~/.rbenv/versions/3.1.5/lib/ruby/gems/3.1.0/gems/nokogiri-1.17.2-arm64-darwin/lib/nokogiri/xml/builder.rb:415:in `method_missing'
	from ~/src/lutaml/lutaml-model/lib/lutaml/model/xml_adapter/builder/nokogiri.rb:87:in `public_send'
	... 32 levels...

It seems that the mapping_rule cannot distinguish annotatedElement whether it is an attribute or element and it try to output XML in wrong way.

@kwkwan kwkwan added the bug Something isn't working label Dec 19, 2024
@HassanAkbar
Copy link
Member

@ronaldtse Currently, we are processing the input data into a hash. If an element and attribute have the same name, the element gets overridden.

Consider the following case:

<ownedComment xmlns:xmi="http://www.omg.org/spec/XMI/20131001" annotatedElement="test2">
  <annotatedElement xmi:idref="ABC"/>
</ownedComment>

Mapping Hash will be:

{ "annotatedElement"=>"test2" }

So, I am considering separating the elements and attributes in a nesting structure within the hash.

{
  "elements" => {
    "annotatedElement" => {
      "elements" => {}, "attributes" => {
        "http://www.omg.org/spec/XMI/20131001:idref" => "ABC"
      }
    },
  },
  "attributes" => {
    "annotatedElement" => "test2"
  }
}

NOTE: This approach might break existing custom methods.

Should we go with this approach? What do you suggest?

@kwkwan
Copy link
Contributor Author

kwkwan commented Jan 2, 2025

@ronaldtse Currently, we are processing the input data into a hash. If an element and attribute have the same name, the element gets overridden.

Consider the following case:

<ownedComment xmlns:xmi="http://www.omg.org/spec/XMI/20131001" annotatedElement="test2">
  <annotatedElement xmi:idref="ABC"/>
</ownedComment>

Mapping Hash will be:

{ "annotatedElement"=>"test2" }

So, I am considering separating the elements and attributes in a nesting structure within the hash.

{
  "elements" => {
    "annotatedElement" => {
      "elements" => {}, "attributes" => {
        "http://www.omg.org/spec/XMI/20131001:idref" => "ABC"
      }
    },
  },
  "attributes" => {
    "annotatedElement" => "test2"
  }
}

NOTE: This approach might break existing custom methods.

Should we go with this approach? What do you suggest?

Hi @ronaldtse, do you think we solve this issue by the quoted approach?

@ronaldtse
Copy link
Contributor

ronaldtse commented Jan 2, 2025

@HassanAkbar I think XML attributes and XML elements should definitely be handled separately, so the proposed approach seems reasonable.

Re: this approach may break custom methods

  • I don't think custom methods should touch the internal structures of the XML mappings.

We do have to remember that other key-value pair serialization methods do not distinguish "attribute" and "element" though.

P.S. This is a blocker for this task:

@ronaldtse
Copy link
Contributor

Ping @kwkwan this issue is now fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants