Open opoudjis opened 2 months ago
What @opoudjis needs is:
The sample XML is this:
<recommendation model="ogc" id="_">
<identifier>/ogc/recommendation/wfs/2</identifier>
<inherit>/ss/584/2015/level/1</inherit>
<subject>user</subject>
<description>
<p id="_">I recommend <em>1</em>.</p>
<classification>
<tag>scope</tag>
<value>random</value>
</classification>
<classification>
<tag>widgets</tag>
<value>randomer</value>
</classification>
</description>
<component class="test-purpose" id="A1"><p>TEST PURPOSE</p></component>
<description><p id="_">I recommend <em>2</em>.</p></description>
<component class="guidance" id="A7"><p>GUIDANCE #1</p></component>
<description><p id="_">I recommend <em>2a</em>.</p></description>
<component class="conditions" id="A2"><p>CONDITIONS</p></component>
<description><p id="_">I recommend <em>3</em>.</p></description>
<component class="part" id="A3"><p>FIRST PART</p></component>
<description><p id="_">I recommend <em>4</em>.</p></description>
<component class="part" id="A4"><p>SECOND PART</p></component>
<description><p id="_">I recommend <em>5</em>.</p></description>
<component class="test-method" id="A5"><p>TEST METHOD</p></component>
<description><p id="_">I recommend <em>6</em>.</p></description>
<component class="part" id="A6"><p>THIRD PART</p></component>
<description><p id="_">I recommend <em>7</em>.</p></description>
<component class="guidance" id="A8"><p>GUIDANCE #2</p></component>
<description><p id="_">I recommend <em>7a</em>.</p></description>
<component class="panda GHz express" id="A7"><p>PANDA PART</p></component>
<description><p id="_">I recommend <em>8</em>.</p></description>
</recommendation>
The pseudocode that parses this could look like this:
class Recommendation < Lutaml::Model::Serializable
attribute :identifier, :string
attribute :inherit, :string
attribute :subject, :string
attribute :description, :string, raw: true, collection: true
attribute :test_purpose, TestPurpose
attribute :test_method, TestMethod
attribute :conditions, Condition, collection: true
attribute :guidance, Guidance, collection: true
attribute :part, Part, collection: true
# 1. Notice that the component / description elements are POSITIONAL.
xml do
map_element "identifier", :identifier
map_element "inherit", :inherit
map_element "subject", :subject
map_element "description", :description
map_element "component", with: {
to: :xml_component_to_specialized,
from: :specialized_to_xml_component
}, attributes: [
:test_purpose,
:test_method,
:conditions,
:guidance,
:part
]
end
def xml_component_to_test_purpose(model, value)
case value['class']
when 'test_purpose'
model.test_purpose << TestPurpose.new(id: value['id'], description: value['text'])
when 'test_method'
model.test_method << TestMethod.new(id: value['id'], description: value['text'])
end
end
def test_purpose_to_xml_component(model, parent, doc)
doc.add_element(
name: 'component',
attribs: { id: model.id, class: model.class.name.underscore },
text: model.description
)
end
end
class TestPurpose < Lutaml::Model::Serializable
attribute :id, :string
attribute :description, :string, raw: true
xml do
map_attribute "id", :id
map_content :description
end
end
The point is we need to facilitate this use case.
@HassanAkbar can you please help work this into viable code and make this work in lutaml-model? Thanks.
Modspec under Metanorma is following the Metanorma modelling of requirements:
component
is an element for general, otherwise unspecified components of requirements.Modspec under modspec-ruby, created by @ronaldtse without talking to me, differentiates
guidance
,purpose
, andmethod
.Under Metanorma, these are
component[@type = 'guidance']
,component[@type = 'purpose']
, andcomponent[@type = 'test-method']
.@ronaldtse wants these deserialised to Metanorma XML under lutaml-model.
I see from the lutaml-model readme that:
I understand that makes life a lot easier for lutaml-model. But that means that lutaml-model forces the XML serialisation (and any serialisation) of a model to have a 1:1 model of its model attributes to its serialisation. I cannot choose to specify where the data goes; and that means I cannot decide that all three of
guidance
,purpose
, andmethod
go tocomponent
, and that there is logic to serialise multiple instances ofcomponent
to one ofguidance
,purpose
, ormethod
.Which means I cannot use lutaml-model, unless I change Metanorma's model to align to modspec-ruby's. Which I'm not going to do, and which is completely unreasonable for a serialisation tool to be forcing me to do.
As it stands,
which is my effort to make this happen, simply doesn't work: it is triggered for
guidance
, doesn't seeguidance
in my test model, and ignores thatpurpose
is in my test model.If lutaml-model is to be usable under the range of serialisation I need in Metanorma, it must be prepared to deal with mismatches in source and target information model. It must give me the freedom I had under Shale, to have complete control over how to serialise the model in custom methods. If it does not do that, then I will need to postprocess its output, to move the tags to where I need them to be.
@ronaldtse You need to decide which of the two to do: make lutaml-model more complicated and more permissive, or be less purist about how I use lutaml-model downstream, and accept that I will postprocess it to get what I want. But as it stands, lutaml-model is not usable for Modspec under Metanorma.
And again, I will absolutely not change my XML model of requirements, just because you made a different modelling choice to me. The serialisation tools do not get to dictate the target model. (And don't assume that this will not keep coming up. Target models can and will mismatch the input model.)