Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 51 additions & 27 deletions lib/read.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,19 @@ ReferenceHandler.prototype.handleNode = function(node) {
this.element = this.createReference(node);
}

const property = this.property;

const idAttr = property.xml && property.xml.idAttr;

if (idAttr && node.attributes[idAttr]) {
this.element.id = node.attributes[idAttr];
}

return this;
};

ReferenceHandler.prototype.handleEnd = function() {
this.element.id = this.body;
this.element.id = this.element.id || this.body;
};

ReferenceHandler.prototype.createReference = function(node) {
Expand Down Expand Up @@ -383,6 +391,44 @@ ElementHandler.prototype.createElement = function(node) {
return instance;
};

/**
* Returns a property with an effective type descriptor,
* in case type is defined through xml -> serialize hint.
*
* @param {any} node parsed
* @param {PropertyDescriptor} property
*
* @return {PropertyDescriptor|null}
*/
ElementHandler.prototype.getSerializeAsTypePropertyForNode = function(node, property) {

const model = this.model;

const serializationType = getSerializationType(property);

if (!serializationType) {
return null;
}

const elementTypeName = node.attributes[serializationType];

// type is optional, if it does not exists the
// default type is assumed
if (elementTypeName) {

// convert the prefix used to the mapped form, but also
// take possible type prefixes from XML
// into account, i.e.: xsi:type="t{ActualType}",
const normalizedTypeName = normalizeTypeName(elementTypeName, node.ns, model);

const elementType = model.getType(normalizedTypeName);

return assign({}, property, {
effectiveType: getModdleDescriptor(elementType).name
});
}
};

ElementHandler.prototype.getPropertyForNode = function(node) {

var name = node.name;
Expand All @@ -398,33 +444,10 @@ ElementHandler.prototype.getPropertyForNode = function(node) {
// search for properties by name first

if (property && !property.isAttr) {

const serializationType = getSerializationType(property);

if (serializationType) {
const elementTypeName = node.attributes[serializationType];

// type is optional, if it does not exists the
// default type is assumed
if (elementTypeName) {

// convert the prefix used to the mapped form, but also
// take possible type prefixes from XML
// into account, i.e.: xsi:type="t{ActualType}",
const normalizedTypeName = normalizeTypeName(elementTypeName, node.ns, model);

const elementType = model.getType(normalizedTypeName);

return assign({}, property, {
effectiveType: getModdleDescriptor(elementType).name
});
}
}

// search for properties by name first
return property;
return this.getSerializeAsTypePropertyForNode(node, property) || property;
}

// search by properties by type
var pkg = model.getPackage(nameNs.prefix);

if (pkg) {
Expand All @@ -437,10 +460,11 @@ ElementHandler.prototype.getPropertyForNode = function(node) {
});

if (property) {
return assign({}, property, {
return this.getSerializeAsTypePropertyForNode(node, property) || assign({}, property, {
effectiveType: getModdleDescriptor(elementType).name
});
}

} else {

// parse unknown element (maybe extension)
Expand Down
27 changes: 21 additions & 6 deletions lib/write.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,16 +245,31 @@ function ReferenceSerializer(tagName) {
this.tagName = tagName;
}

ReferenceSerializer.prototype.build = function(element) {
ReferenceSerializer.prototype.build = function(property, element) {
this.property = property;
this.element = element;

return this;
};

ReferenceSerializer.prototype.serializeTo = function(writer) {
writer
.appendIndent()
.append('<' + this.tagName + '>' + this.element.id + '</' + this.tagName + '>')
.appendNewLine();

const property = this.property;

const idAttr = property.xml && property.xml.idAttr;

const id = this.element.id;
const tagName = this.tagName;

writer.appendIndent();

if (idAttr) {
writer.append('<' + tagName + ' ' + idAttr + '="' + id + '" />');
} else {
writer.append('<' + tagName + '>' + id + '</' + tagName + '>');
}

writer.appendNewLine();
};

function BodySerializer() {}
Expand Down Expand Up @@ -532,7 +547,7 @@ ElementSerializer.prototype.parseContainments = function(properties) {
} else
if (isReference) {
forEach(value, function(v) {
body.push(new ReferenceSerializer(self.addTagName(self.nsPropertyTagName(p))).build(v));
body.push(new ReferenceSerializer(self.addTagName(self.nsPropertyTagName(p))).build(p, v));
});
} else {

Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "moddle-xml",
"version": "10.1.0",
"version": "11.0.0-exp.4",
"description": "XML import/export for documents described with moddle",
"scripts": {
"all": "run-s lint test distro",
Expand Down Expand Up @@ -54,7 +54,7 @@
"eslint": "^8.34.0",
"eslint-plugin-bpmn-io": "^1.0.0",
"mocha": "^10.0.0",
"moddle": "^6.2.0",
"moddle": "^7.0.0-exp.3",
"npm-run-all": "^4.1.5",
"rollup": "^3.17.2"
},
Expand Down
14 changes: 14 additions & 0 deletions test/fixtures/model/properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@
}
]
},
{
"name": "ReferencingNestedRef",
"superClass": [ "BaseWithId" ],
"properties": [
{
"name": "referencedComplex",
"type": "Complex",
"isReference": true,
"xml": {
"idAttr": "idref"
}
}
]
},
{
"name": "ReferencingCollection",
"superClass": [ "BaseWithId" ],
Expand Down
19 changes: 19 additions & 0 deletions test/fixtures/model/uml/uml.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "UML",
"uri": "http://www.omg.org/spec/UML/20131001",
"prefix": "uml",
"types": [
{
"name": "Package",
"superClass": [
"xmi:Extension"
]
},
{
"name": "SpecialPackage",
"superClass": [
"Package"
]
}
]
}
32 changes: 32 additions & 0 deletions test/fixtures/model/uml/xmi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "XMI",
"uri": "http://www.omg.org/spec/XMI/20131001",
"prefix": "xmi",
"types": [
{
"name": "XMI",
"properties": [
{ "name": "extension", "type": "Extension", "isMany": true, "xml": { "serialize": "xmi:type" } }
]
},
{
"name": "Extension",
"superClass": [
"Element"
]
},
{
"name": "Typed",
"extends": [
"xmi:Extension"
],
"properties": [
{
"name": "type",
"type": "String",
"isAttr": true
}
]
}
]
}
Empty file added test/fixtures/xml/XMI.xmi
Empty file.
Loading