moddle-xml
Version:
XML import/export for documents described with moddle
1 lines • 93.2 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../lib/common.js","../lib/read.js","../lib/write.js"],"sourcesContent":["export function hasLowerCaseAlias(pkg) {\n return pkg.xml && pkg.xml.tagAlias === 'lowerCase';\n}\n\nexport var DEFAULT_NS_MAP = {\n 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',\n 'xml': 'http://www.w3.org/XML/1998/namespace'\n};\n\nexport var SERIALIZE_PROPERTY = 'property';\n\nexport function getSerialization(element) {\n return element.xml && element.xml.serialize;\n}\n\nexport function getSerializationType(element) {\n const type = getSerialization(element);\n\n return type !== SERIALIZE_PROPERTY && (type || null);\n}","import {\n forEach,\n find,\n assign\n} from 'min-dash';\n\nimport {\n Parser as SaxParser\n} from 'saxen';\n\nimport {\n Moddle,\n parseNameNS,\n coerceType,\n isSimpleType\n} from 'moddle';\n\nimport {\n DEFAULT_NS_MAP,\n getSerializationType,\n hasLowerCaseAlias\n} from './common.js';\n\nfunction capitalize(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nfunction aliasToName(aliasNs, pkg) {\n\n if (!hasLowerCaseAlias(pkg)) {\n return aliasNs.name;\n }\n\n return aliasNs.prefix + ':' + capitalize(aliasNs.localName);\n}\n\n/**\n * Un-prefix a potentially prefixed type name.\n *\n * @param {NsName} nameNs\n * @param {Object} [pkg]\n *\n * @return {string}\n */\nfunction prefixedToName(nameNs, pkg) {\n\n var name = nameNs.name,\n localName = nameNs.localName;\n\n var typePrefix = pkg && pkg.xml && pkg.xml.typePrefix;\n\n if (typePrefix && localName.indexOf(typePrefix) === 0) {\n return nameNs.prefix + ':' + localName.slice(typePrefix.length);\n } else {\n return name;\n }\n}\n\nfunction normalizeTypeName(name, nsMap, model) {\n\n // normalize against actual NS\n const nameNs = parseNameNS(name, nsMap.xmlns);\n\n const normalizedName = `${ nsMap[nameNs.prefix] || nameNs.prefix }:${ nameNs.localName }`;\n\n const normalizedNameNs = parseNameNS(normalizedName);\n\n // determine actual type name, based on package-defined prefix\n var pkg = model.getPackage(normalizedNameNs.prefix);\n\n return prefixedToName(normalizedNameNs, pkg);\n}\n\nfunction error(message) {\n return new Error(message);\n}\n\n/**\n * Get the moddle descriptor for a given instance or type.\n *\n * @param {ModdleElement|Function} element\n *\n * @return {Object} the moddle descriptor\n */\nfunction getModdleDescriptor(element) {\n return element.$descriptor;\n}\n\n\n/**\n * A parse context.\n *\n * @class\n *\n * @param {Object} options\n * @param {ElementHandler} options.rootHandler the root handler for parsing a document\n * @param {boolean} [options.lax=false] whether or not to ignore invalid elements\n */\nexport function Context(options) {\n\n /**\n * @property {ElementHandler} rootHandler\n */\n\n /**\n * @property {Boolean} lax\n */\n\n assign(this, options);\n\n this.elementsById = {};\n this.references = [];\n this.warnings = [];\n\n /**\n * Add an unresolved reference.\n *\n * @param {Object} reference\n */\n this.addReference = function(reference) {\n this.references.push(reference);\n };\n\n /**\n * Add a processed element.\n *\n * @param {ModdleElement} element\n */\n this.addElement = function(element) {\n\n if (!element) {\n throw error('expected element');\n }\n\n var elementsById = this.elementsById;\n\n var descriptor = getModdleDescriptor(element);\n\n var idProperty = descriptor.idProperty,\n id;\n\n if (idProperty) {\n id = element.get(idProperty.name);\n\n if (id) {\n\n // for QName validation as per http://www.w3.org/TR/REC-xml/#NT-NameChar\n if (!/^([a-z][\\w-.]*:)?[a-z_][\\w-.]*$/i.test(id)) {\n throw new Error('illegal ID <' + id + '>');\n }\n\n if (elementsById[id]) {\n throw error('duplicate ID <' + id + '>');\n }\n\n elementsById[id] = element;\n }\n }\n };\n\n /**\n * Add an import warning.\n *\n * @param {Object} warning\n * @param {String} warning.message\n * @param {Error} [warning.error]\n */\n this.addWarning = function(warning) {\n this.warnings.push(warning);\n };\n}\n\nfunction BaseHandler() {}\n\nBaseHandler.prototype.handleEnd = function() {};\nBaseHandler.prototype.handleText = function() {};\nBaseHandler.prototype.handleNode = function() {};\n\n\n/**\n * A simple pass through handler that does nothing except for\n * ignoring all input it receives.\n *\n * This is used to ignore unknown elements and\n * attributes.\n */\nfunction NoopHandler() { }\n\nNoopHandler.prototype = Object.create(BaseHandler.prototype);\n\nNoopHandler.prototype.handleNode = function() {\n return this;\n};\n\nfunction BodyHandler() {}\n\nBodyHandler.prototype = Object.create(BaseHandler.prototype);\n\nBodyHandler.prototype.handleText = function(text) {\n this.body = (this.body || '') + text;\n};\n\nfunction ReferenceHandler(property, context) {\n this.property = property;\n this.context = context;\n}\n\nReferenceHandler.prototype = Object.create(BodyHandler.prototype);\n\nReferenceHandler.prototype.handleNode = function(node) {\n\n if (this.element) {\n throw error('expected no sub nodes');\n } else {\n this.element = this.createReference(node);\n }\n\n return this;\n};\n\nReferenceHandler.prototype.handleEnd = function() {\n this.element.id = this.body;\n};\n\nReferenceHandler.prototype.createReference = function(node) {\n return {\n property: this.property.ns.name,\n id: ''\n };\n};\n\nfunction ValueHandler(propertyDesc, element) {\n this.element = element;\n this.propertyDesc = propertyDesc;\n}\n\nValueHandler.prototype = Object.create(BodyHandler.prototype);\n\nValueHandler.prototype.handleEnd = function() {\n\n var value = this.body || '',\n element = this.element,\n propertyDesc = this.propertyDesc;\n\n value = coerceType(propertyDesc.type, value);\n\n if (propertyDesc.isMany) {\n element.get(propertyDesc.name).push(value);\n } else {\n element.set(propertyDesc.name, value);\n }\n};\n\n\nfunction BaseElementHandler() {}\n\nBaseElementHandler.prototype = Object.create(BodyHandler.prototype);\n\nBaseElementHandler.prototype.handleNode = function(node) {\n var parser = this,\n element = this.element;\n\n if (!element) {\n element = this.element = this.createElement(node);\n\n this.context.addElement(element);\n } else {\n parser = this.handleChild(node);\n }\n\n return parser;\n};\n\n/**\n * @class Reader.ElementHandler\n *\n */\nexport function ElementHandler(model, typeName, context) {\n this.model = model;\n this.type = model.getType(typeName);\n this.context = context;\n}\n\nElementHandler.prototype = Object.create(BaseElementHandler.prototype);\n\nElementHandler.prototype.addReference = function(reference) {\n this.context.addReference(reference);\n};\n\nElementHandler.prototype.handleText = function(text) {\n\n var element = this.element,\n descriptor = getModdleDescriptor(element),\n bodyProperty = descriptor.bodyProperty;\n\n if (!bodyProperty) {\n throw error('unexpected body text <' + text + '>');\n }\n\n BodyHandler.prototype.handleText.call(this, text);\n};\n\nElementHandler.prototype.handleEnd = function() {\n\n var value = this.body,\n element = this.element,\n descriptor = getModdleDescriptor(element),\n bodyProperty = descriptor.bodyProperty;\n\n if (bodyProperty && value !== undefined) {\n value = coerceType(bodyProperty.type, value);\n element.set(bodyProperty.name, value);\n }\n};\n\n/**\n * Create an instance of the model from the given node.\n *\n * @param {Element} node the xml node\n */\nElementHandler.prototype.createElement = function(node) {\n var attributes = node.attributes,\n Type = this.type,\n descriptor = getModdleDescriptor(Type),\n context = this.context,\n instance = new Type({}),\n model = this.model,\n propNameNs;\n\n forEach(attributes, function(value, name) {\n\n var prop = descriptor.propertiesByName[name],\n values;\n\n if (prop && prop.isReference) {\n\n if (!prop.isMany) {\n context.addReference({\n element: instance,\n property: prop.ns.name,\n id: value\n });\n } else {\n\n // IDREFS: parse references as whitespace-separated list\n values = value.split(' ');\n\n forEach(values, function(v) {\n context.addReference({\n element: instance,\n property: prop.ns.name,\n id: v\n });\n });\n }\n\n } else {\n if (prop) {\n value = coerceType(prop.type, value);\n } else if (name === 'xmlns') {\n name = ':' + name;\n } else {\n propNameNs = parseNameNS(name, descriptor.ns.prefix);\n\n // check whether attribute is defined in a well-known namespace\n // if that is the case we emit a warning to indicate potential misuse\n if (model.getPackage(propNameNs.prefix)) {\n\n context.addWarning({\n message: 'unknown attribute <' + name + '>',\n element: instance,\n property: name,\n value: value\n });\n }\n }\n\n instance.set(name, value);\n }\n });\n\n return instance;\n};\n\nElementHandler.prototype.getPropertyForNode = function(node) {\n\n var name = node.name;\n var nameNs = parseNameNS(name);\n\n var type = this.type,\n model = this.model,\n descriptor = getModdleDescriptor(type);\n\n var propertyName = nameNs.name,\n property = descriptor.propertiesByName[propertyName];\n\n // search for properties by name first\n\n if (property && !property.isAttr) {\n\n const serializationType = getSerializationType(property);\n\n if (serializationType) {\n const elementTypeName = node.attributes[serializationType];\n\n // type is optional, if it does not exists the\n // default type is assumed\n if (elementTypeName) {\n\n // convert the prefix used to the mapped form, but also\n // take possible type prefixes from XML\n // into account, i.e.: xsi:type=\"t{ActualType}\",\n const normalizedTypeName = normalizeTypeName(elementTypeName, node.ns, model);\n\n const elementType = model.getType(normalizedTypeName);\n\n return assign({}, property, {\n effectiveType: getModdleDescriptor(elementType).name\n });\n }\n }\n\n // search for properties by name first\n return property;\n }\n\n var pkg = model.getPackage(nameNs.prefix);\n\n if (pkg) {\n const elementTypeName = aliasToName(nameNs, pkg);\n const elementType = model.getType(elementTypeName);\n\n // search for collection members later\n property = find(descriptor.properties, function(p) {\n return !p.isVirtual && !p.isReference && !p.isAttribute && elementType.hasType(p.type);\n });\n\n if (property) {\n return assign({}, property, {\n effectiveType: getModdleDescriptor(elementType).name\n });\n }\n } else {\n\n // parse unknown element (maybe extension)\n property = find(descriptor.properties, function(p) {\n return !p.isReference && !p.isAttribute && p.type === 'Element';\n });\n\n if (property) {\n return property;\n }\n }\n\n throw error('unrecognized element <' + nameNs.name + '>');\n};\n\nElementHandler.prototype.toString = function() {\n return 'ElementDescriptor[' + getModdleDescriptor(this.type).name + ']';\n};\n\nElementHandler.prototype.valueHandler = function(propertyDesc, element) {\n return new ValueHandler(propertyDesc, element);\n};\n\nElementHandler.prototype.referenceHandler = function(propertyDesc) {\n return new ReferenceHandler(propertyDesc, this.context);\n};\n\nElementHandler.prototype.handler = function(type) {\n if (type === 'Element') {\n return new GenericElementHandler(this.model, type, this.context);\n } else {\n return new ElementHandler(this.model, type, this.context);\n }\n};\n\n/**\n * Handle the child element parsing\n *\n * @param {Element} node the xml node\n */\nElementHandler.prototype.handleChild = function(node) {\n var propertyDesc, type, element, childHandler;\n\n propertyDesc = this.getPropertyForNode(node);\n element = this.element;\n\n type = propertyDesc.effectiveType || propertyDesc.type;\n\n if (isSimpleType(type)) {\n return this.valueHandler(propertyDesc, element);\n }\n\n if (propertyDesc.isReference) {\n childHandler = this.referenceHandler(propertyDesc).handleNode(node);\n } else {\n childHandler = this.handler(type).handleNode(node);\n }\n\n var newElement = childHandler.element;\n\n // child handles may decide to skip elements\n // by not returning anything\n if (newElement !== undefined) {\n\n if (propertyDesc.isMany) {\n element.get(propertyDesc.name).push(newElement);\n } else {\n element.set(propertyDesc.name, newElement);\n }\n\n if (propertyDesc.isReference) {\n assign(newElement, {\n element: element\n });\n\n this.context.addReference(newElement);\n } else {\n\n // establish child -> parent relationship\n newElement.$parent = element;\n }\n }\n\n return childHandler;\n};\n\n/**\n * An element handler that performs special validation\n * to ensure the node it gets initialized with matches\n * the handlers type (namespace wise).\n *\n * @param {Moddle} model\n * @param {String} typeName\n * @param {Context} context\n */\nfunction RootElementHandler(model, typeName, context) {\n ElementHandler.call(this, model, typeName, context);\n}\n\nRootElementHandler.prototype = Object.create(ElementHandler.prototype);\n\nRootElementHandler.prototype.createElement = function(node) {\n\n var name = node.name,\n nameNs = parseNameNS(name),\n model = this.model,\n type = this.type,\n pkg = model.getPackage(nameNs.prefix),\n typeName = pkg && aliasToName(nameNs, pkg) || name;\n\n // verify the correct namespace if we parse\n // the first element in the handler tree\n //\n // this ensures we don't mistakenly import wrong namespace elements\n if (!type.hasType(typeName)) {\n throw error('unexpected element <' + node.originalName + '>');\n }\n\n return ElementHandler.prototype.createElement.call(this, node);\n};\n\n\nfunction GenericElementHandler(model, typeName, context) {\n this.model = model;\n this.context = context;\n}\n\nGenericElementHandler.prototype = Object.create(BaseElementHandler.prototype);\n\nGenericElementHandler.prototype.createElement = function(node) {\n\n var name = node.name,\n ns = parseNameNS(name),\n prefix = ns.prefix,\n uri = node.ns[prefix + '$uri'],\n attributes = node.attributes;\n\n return this.model.createAny(name, uri, attributes);\n};\n\nGenericElementHandler.prototype.handleChild = function(node) {\n\n var handler = new GenericElementHandler(this.model, 'Element', this.context).handleNode(node),\n element = this.element;\n\n var newElement = handler.element,\n children;\n\n if (newElement !== undefined) {\n children = element.$children = element.$children || [];\n children.push(newElement);\n\n // establish child -> parent relationship\n newElement.$parent = element;\n }\n\n return handler;\n};\n\nGenericElementHandler.prototype.handleEnd = function() {\n if (this.body) {\n this.element.$body = this.body;\n }\n};\n\n/**\n * A reader for a meta-model\n *\n * @param {Object} options\n * @param {Model} options.model used to read xml files\n * @param {Boolean} options.lax whether to make parse errors warnings\n */\nexport function Reader(options) {\n\n if (options instanceof Moddle) {\n options = {\n model: options\n };\n }\n\n assign(this, { lax: false }, options);\n}\n\n/**\n * The fromXML result.\n *\n * @typedef {Object} ParseResult\n *\n * @property {ModdleElement} rootElement\n * @property {Array<Object>} references\n * @property {Array<Error>} warnings\n * @property {Object} elementsById - a mapping containing each ID -> ModdleElement\n */\n\n/**\n * The fromXML result.\n *\n * @typedef {Error} ParseError\n *\n * @property {Array<Error>} warnings\n */\n\n/**\n * Parse the given XML into a moddle document tree.\n *\n * @param {String} xml\n * @param {ElementHandler|Object} options or rootHandler\n *\n * @returns {Promise<ParseResult, ParseError>}\n */\nReader.prototype.fromXML = function(xml, options, done) {\n\n var rootHandler = options.rootHandler;\n\n if (options instanceof ElementHandler) {\n\n // root handler passed via (xml, { rootHandler: ElementHandler }, ...)\n rootHandler = options;\n options = {};\n } else {\n if (typeof options === 'string') {\n\n // rootHandler passed via (xml, 'someString', ...)\n rootHandler = this.handler(options);\n options = {};\n } else if (typeof rootHandler === 'string') {\n\n // rootHandler passed via (xml, { rootHandler: 'someString' }, ...)\n rootHandler = this.handler(rootHandler);\n }\n }\n\n var model = this.model,\n lax = this.lax;\n\n var context = new Context(assign({}, options, { rootHandler: rootHandler })),\n parser = new SaxParser({ proxy: true }),\n stack = createStack();\n\n rootHandler.context = context;\n\n // push root handler\n stack.push(rootHandler);\n\n\n /**\n * Handle error.\n *\n * @param {Error} err\n * @param {Function} getContext\n * @param {boolean} lax\n *\n * @return {boolean} true if handled\n */\n function handleError(err, getContext, lax) {\n\n var ctx = getContext();\n\n var line = ctx.line,\n column = ctx.column,\n data = ctx.data;\n\n // we receive the full context data here,\n // for elements trim down the information\n // to the tag name, only\n if (data.charAt(0) === '<' && data.indexOf(' ') !== -1) {\n data = data.slice(0, data.indexOf(' ')) + '>';\n }\n\n var message =\n 'unparsable content ' + (data ? data + ' ' : '') + 'detected\\n\\t' +\n 'line: ' + line + '\\n\\t' +\n 'column: ' + column + '\\n\\t' +\n 'nested error: ' + err.message;\n\n if (lax) {\n context.addWarning({\n message: message,\n error: err\n });\n\n return true;\n } else {\n throw error(message);\n }\n }\n\n function handleWarning(err, getContext) {\n\n // just like handling errors in <lax=true> mode\n return handleError(err, getContext, true);\n }\n\n /**\n * Resolve collected references on parse end.\n */\n function resolveReferences() {\n\n var elementsById = context.elementsById;\n var references = context.references;\n\n var i, r;\n\n for (i = 0; (r = references[i]); i++) {\n var element = r.element;\n var reference = elementsById[r.id];\n var property = getModdleDescriptor(element).propertiesByName[r.property];\n\n if (!reference) {\n context.addWarning({\n message: 'unresolved reference <' + r.id + '>',\n element: r.element,\n property: r.property,\n value: r.id\n });\n }\n\n if (property.isMany) {\n var collection = element.get(property.name),\n idx = collection.indexOf(r);\n\n // we replace an existing place holder (idx != -1) or\n // append to the collection instead\n if (idx === -1) {\n idx = collection.length;\n }\n\n if (!reference) {\n\n // remove unresolvable reference\n collection.splice(idx, 1);\n } else {\n\n // add or update reference in collection\n collection[idx] = reference;\n }\n } else {\n element.set(property.name, reference);\n }\n }\n }\n\n function handleClose() {\n stack.pop().handleEnd();\n }\n\n var PREAMBLE_START_PATTERN = /^<\\?xml /i;\n\n var ENCODING_PATTERN = / encoding=\"([^\"]+)\"/i;\n\n var UTF_8_PATTERN = /^utf-8$/i;\n\n function handleQuestion(question) {\n\n if (!PREAMBLE_START_PATTERN.test(question)) {\n return;\n }\n\n var match = ENCODING_PATTERN.exec(question);\n var encoding = match && match[1];\n\n if (!encoding || UTF_8_PATTERN.test(encoding)) {\n return;\n }\n\n context.addWarning({\n message:\n 'unsupported document encoding <' + encoding + '>, ' +\n 'falling back to UTF-8'\n });\n }\n\n function handleOpen(node, getContext) {\n var handler = stack.peek();\n\n try {\n stack.push(handler.handleNode(node));\n } catch (err) {\n\n if (handleError(err, getContext, lax)) {\n stack.push(new NoopHandler());\n }\n }\n }\n\n function handleCData(text, getContext) {\n\n try {\n stack.peek().handleText(text);\n } catch (err) {\n handleWarning(err, getContext);\n }\n }\n\n function handleText(text, getContext) {\n\n // strip whitespace only nodes, i.e. before\n // <!CDATA[ ... ]> sections and in between tags\n\n if (!text.trim()) {\n return;\n }\n\n handleCData(text, getContext);\n }\n\n var uriMap = model.getPackages().reduce(function(uriMap, p) {\n uriMap[p.uri] = p.prefix;\n\n return uriMap;\n }, Object.entries(DEFAULT_NS_MAP).reduce(function(map, [ prefix, url ]) {\n map[url] = prefix;\n\n return map;\n }, model.config && model.config.nsMap || {}));\n\n parser\n .ns(uriMap)\n .on('openTag', function(obj, decodeStr, selfClosing, getContext) {\n\n // gracefully handle unparsable attributes (attrs=false)\n var attrs = obj.attrs || {};\n\n var decodedAttrs = Object.keys(attrs).reduce(function(d, key) {\n var value = decodeStr(attrs[key]);\n\n d[key] = value;\n\n return d;\n }, {});\n\n var node = {\n name: obj.name,\n originalName: obj.originalName,\n attributes: decodedAttrs,\n ns: obj.ns\n };\n\n handleOpen(node, getContext);\n })\n .on('question', handleQuestion)\n .on('closeTag', handleClose)\n .on('cdata', handleCData)\n .on('text', function(text, decodeEntities, getContext) {\n handleText(decodeEntities(text), getContext);\n })\n .on('error', handleError)\n .on('warn', handleWarning);\n\n // async XML parsing to make sure the execution environment\n // (node or brower) is kept responsive and that certain optimization\n // strategies can kick in.\n return new Promise(function(resolve, reject) {\n\n var err;\n\n try {\n parser.parse(xml);\n\n resolveReferences();\n } catch (e) {\n err = e;\n }\n\n var rootElement = rootHandler.element;\n\n if (!err && !rootElement) {\n err = error('failed to parse document as <' + rootHandler.type.$descriptor.name + '>');\n }\n\n var warnings = context.warnings;\n var references = context.references;\n var elementsById = context.elementsById;\n\n if (err) {\n err.warnings = warnings;\n\n return reject(err);\n } else {\n return resolve({\n rootElement: rootElement,\n elementsById: elementsById,\n references: references,\n warnings: warnings\n });\n }\n });\n};\n\nReader.prototype.handler = function(name) {\n return new RootElementHandler(this.model, name);\n};\n\n\n// helpers //////////////////////////\n\nfunction createStack() {\n var stack = [];\n\n Object.defineProperty(stack, 'peek', {\n value: function() {\n return this[this.length - 1];\n }\n });\n\n return stack;\n}\n","import {\n forEach,\n isString,\n filter,\n assign,\n has,\n findIndex\n} from 'min-dash';\n\nimport {\n isSimpleType,\n parseNameNS\n} from 'moddle';\n\nimport {\n hasLowerCaseAlias,\n getSerialization,\n SERIALIZE_PROPERTY,\n DEFAULT_NS_MAP\n} from './common.js';\n\nvar XML_PREAMBLE = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n\nvar ESCAPE_ATTR_CHARS = /<|>|'|\"|&|\\n\\r|\\n/g;\nvar ESCAPE_CHARS = /<|>|&/g;\n\n\nexport function Namespaces(parent) {\n\n this.prefixMap = {};\n this.uriMap = {};\n this.used = {};\n\n this.wellknown = [];\n this.custom = [];\n this.parent = parent;\n\n this.defaultPrefixMap = parent && parent.defaultPrefixMap || {};\n}\n\nNamespaces.prototype.mapDefaultPrefixes = function(defaultPrefixMap) {\n this.defaultPrefixMap = defaultPrefixMap;\n};\n\nNamespaces.prototype.defaultUriByPrefix = function(prefix) {\n return this.defaultPrefixMap[prefix];\n};\n\nNamespaces.prototype.byUri = function(uri) {\n return this.uriMap[uri] || (\n this.parent && this.parent.byUri(uri)\n );\n};\n\nNamespaces.prototype.add = function(ns, isWellknown) {\n\n this.uriMap[ns.uri] = ns;\n\n if (isWellknown) {\n this.wellknown.push(ns);\n } else {\n this.custom.push(ns);\n }\n\n this.mapPrefix(ns.prefix, ns.uri);\n};\n\nNamespaces.prototype.uriByPrefix = function(prefix) {\n return this.prefixMap[prefix || 'xmlns'] || (\n this.parent && this.parent.uriByPrefix(prefix)\n );\n};\n\nNamespaces.prototype.mapPrefix = function(prefix, uri) {\n this.prefixMap[prefix || 'xmlns'] = uri;\n};\n\nNamespaces.prototype.getNSKey = function(ns) {\n return (ns.prefix !== undefined) ? (ns.uri + '|' + ns.prefix) : ns.uri;\n};\n\nNamespaces.prototype.logUsed = function(ns) {\n\n var uri = ns.uri;\n var nsKey = this.getNSKey(ns);\n\n this.used[nsKey] = this.byUri(uri);\n\n // Inform parent recursively about the usage of this NS\n if (this.parent) {\n this.parent.logUsed(ns);\n }\n};\n\nNamespaces.prototype.getUsed = function(ns) {\n\n var allNs = [].concat(this.wellknown, this.custom);\n\n return allNs.filter(ns => {\n var nsKey = this.getNSKey(ns);\n\n return this.used[nsKey];\n });\n};\n\n\nfunction lower(string) {\n return string.charAt(0).toLowerCase() + string.slice(1);\n}\n\nfunction nameToAlias(name, pkg) {\n if (hasLowerCaseAlias(pkg)) {\n return lower(name);\n } else {\n return name;\n }\n}\n\nfunction inherits(ctor, superCtor) {\n ctor.super_ = superCtor;\n ctor.prototype = Object.create(superCtor.prototype, {\n constructor: {\n value: ctor,\n enumerable: false,\n writable: true,\n configurable: true\n }\n });\n}\n\nfunction nsName(ns) {\n if (isString(ns)) {\n return ns;\n } else {\n return (ns.prefix ? ns.prefix + ':' : '') + ns.localName;\n }\n}\n\nfunction getNsAttrs(namespaces) {\n\n return namespaces.getUsed().filter(function(ns) {\n\n // do not serialize built in <xml> namespace\n return ns.prefix !== 'xml';\n }).map(function(ns) {\n var name = 'xmlns' + (ns.prefix ? ':' + ns.prefix : '');\n return { name: name, value: ns.uri };\n });\n\n}\n\nfunction getElementNs(ns, descriptor) {\n if (descriptor.isGeneric) {\n return assign({ localName: descriptor.ns.localName }, ns);\n } else {\n return assign({ localName: nameToAlias(descriptor.ns.localName, descriptor.$pkg) }, ns);\n }\n}\n\nfunction getPropertyNs(ns, descriptor) {\n return assign({ localName: descriptor.ns.localName }, ns);\n}\n\nfunction getSerializableProperties(element) {\n var descriptor = element.$descriptor;\n\n return filter(descriptor.properties, function(p) {\n var name = p.name;\n\n if (p.isVirtual) {\n return false;\n }\n\n // do not serialize defaults\n if (!has(element, name)) {\n return false;\n }\n\n var value = element[name];\n\n // do not serialize default equals\n if (value === p.default) {\n return false;\n }\n\n // do not serialize null properties\n if (value === null) {\n return false;\n }\n\n return p.isMany ? value.length : true;\n });\n}\n\nvar ESCAPE_ATTR_MAP = {\n '\\n': '#10',\n '\\n\\r': '#10',\n '\"': '#34',\n '\\'': '#39',\n '<': '#60',\n '>': '#62',\n '&': '#38'\n};\n\nvar ESCAPE_MAP = {\n '<': 'lt',\n '>': 'gt',\n '&': 'amp'\n};\n\nfunction escape(str, charPattern, replaceMap) {\n\n // ensure we are handling strings here\n str = isString(str) ? str : '' + str;\n\n return str.replace(charPattern, function(s) {\n return '&' + replaceMap[s] + ';';\n });\n}\n\n/**\n * Escape a string attribute to not contain any bad values (line breaks, '\"', ...)\n *\n * @param {String} str the string to escape\n * @return {String} the escaped string\n */\nfunction escapeAttr(str) {\n return escape(str, ESCAPE_ATTR_CHARS, ESCAPE_ATTR_MAP);\n}\n\nfunction escapeBody(str) {\n return escape(str, ESCAPE_CHARS, ESCAPE_MAP);\n}\n\nfunction filterAttributes(props) {\n return filter(props, function(p) { return p.isAttr; });\n}\n\nfunction filterContained(props) {\n return filter(props, function(p) { return !p.isAttr; });\n}\n\n\nfunction ReferenceSerializer(tagName) {\n this.tagName = tagName;\n}\n\nReferenceSerializer.prototype.build = function(element) {\n this.element = element;\n return this;\n};\n\nReferenceSerializer.prototype.serializeTo = function(writer) {\n writer\n .appendIndent()\n .append('<' + this.tagName + '>' + this.element.id + '</' + this.tagName + '>')\n .appendNewLine();\n};\n\nfunction BodySerializer() {}\n\nBodySerializer.prototype.serializeValue =\nBodySerializer.prototype.serializeTo = function(writer) {\n writer.append(\n this.escape\n ? escapeBody(this.value)\n : this.value\n );\n};\n\nBodySerializer.prototype.build = function(prop, value) {\n this.value = value;\n\n if (prop.type === 'String' && value.search(ESCAPE_CHARS) !== -1) {\n this.escape = true;\n }\n\n return this;\n};\n\nfunction ValueSerializer(tagName) {\n this.tagName = tagName;\n}\n\ninherits(ValueSerializer, BodySerializer);\n\nValueSerializer.prototype.serializeTo = function(writer) {\n\n writer\n .appendIndent()\n .append('<' + this.tagName + '>');\n\n this.serializeValue(writer);\n\n writer\n .append('</' + this.tagName + '>')\n .appendNewLine();\n};\n\nfunction ElementSerializer(parent, propertyDescriptor) {\n this.body = [];\n this.attrs = [];\n\n this.parent = parent;\n this.propertyDescriptor = propertyDescriptor;\n}\n\nElementSerializer.prototype.build = function(element) {\n this.element = element;\n\n var elementDescriptor = element.$descriptor,\n propertyDescriptor = this.propertyDescriptor;\n\n var otherAttrs,\n properties;\n\n var isGeneric = elementDescriptor.isGeneric;\n\n if (isGeneric) {\n otherAttrs = this.parseGenericNsAttributes(element);\n } else {\n otherAttrs = this.parseNsAttributes(element);\n }\n\n if (propertyDescriptor) {\n this.ns = this.nsPropertyTagName(propertyDescriptor);\n } else {\n this.ns = this.nsTagName(elementDescriptor);\n }\n\n // compute tag name\n this.tagName = this.addTagName(this.ns);\n\n if (isGeneric) {\n this.parseGenericContainments(element);\n } else {\n properties = getSerializableProperties(element);\n\n this.parseAttributes(filterAttributes(properties));\n this.parseContainments(filterContained(properties));\n }\n\n this.parseGenericAttributes(element, otherAttrs);\n\n return this;\n};\n\nElementSerializer.prototype.nsTagName = function(descriptor) {\n var effectiveNs = this.logNamespaceUsed(descriptor.ns);\n return getElementNs(effectiveNs, descriptor);\n};\n\nElementSerializer.prototype.nsPropertyTagName = function(descriptor) {\n var effectiveNs = this.logNamespaceUsed(descriptor.ns);\n return getPropertyNs(effectiveNs, descriptor);\n};\n\nElementSerializer.prototype.isLocalNs = function(ns) {\n return ns.uri === this.ns.uri;\n};\n\n/**\n * Get the actual ns attribute name for the given element.\n *\n * @param {Object} element\n * @param {Boolean} [element.inherited=false]\n *\n * @return {Object} nsName\n */\nElementSerializer.prototype.nsAttributeName = function(element) {\n\n var ns;\n\n if (isString(element)) {\n ns = parseNameNS(element);\n } else {\n ns = element.ns;\n }\n\n // return just local name for inherited attributes\n if (element.inherited) {\n return { localName: ns.localName };\n }\n\n // parse + log effective ns\n var effectiveNs = this.logNamespaceUsed(ns);\n\n // LOG ACTUAL namespace use\n this.getNamespaces().logUsed(effectiveNs);\n\n // strip prefix if same namespace like parent\n if (this.isLocalNs(effectiveNs)) {\n return { localName: ns.localName };\n } else {\n return assign({ localName: ns.localName }, effectiveNs);\n }\n};\n\nElementSerializer.prototype.parseGenericNsAttributes = function(element) {\n\n return Object.entries(element).filter(\n ([ key, value ]) => !key.startsWith('$') && this.parseNsAttribute(element, key, value)\n ).map(\n ([ key, value ]) => ({ name: key, value: value })\n );\n};\n\nElementSerializer.prototype.parseGenericContainments = function(element) {\n var body = element.$body;\n\n if (body) {\n this.body.push(new BodySerializer().build({ type: 'String' }, body));\n }\n\n var children = element.$children;\n\n if (children) {\n forEach(children, child => {\n this.body.push(new ElementSerializer(this).build(child));\n });\n }\n};\n\nElementSerializer.prototype.parseNsAttribute = function(element, name, value) {\n var model = element.$model;\n\n var nameNs = parseNameNS(name);\n\n var ns;\n\n // parse xmlns:foo=\"http://foo.bar\"\n if (nameNs.prefix === 'xmlns') {\n ns = { prefix: nameNs.localName, uri: value };\n }\n\n // parse xmlns=\"http://foo.bar\"\n if (!nameNs.prefix && nameNs.localName === 'xmlns') {\n ns = { uri: value };\n }\n\n if (!ns) {\n return {\n name: name,\n value: value\n };\n }\n\n if (model && model.getPackage(value)) {\n\n // register well known namespace\n this.logNamespace(ns, true, true);\n } else {\n\n // log custom namespace directly as used\n var actualNs = this.logNamespaceUsed(ns, true);\n\n this.getNamespaces().logUsed(actualNs);\n }\n};\n\n\n/**\n * Parse namespaces and return a list of left over generic attributes\n *\n * @param {Object} element\n * @return {Array<Object>}\n */\nElementSerializer.prototype.parseNsAttributes = function(element) {\n var self = this;\n\n var genericAttrs = element.$attrs;\n\n var attributes = [];\n\n // parse namespace attributes first\n // and log them. push non namespace attributes to a list\n // and process them later\n forEach(genericAttrs, function(value, name) {\n\n var nonNsAttr = self.parseNsAttribute(element, name, value);\n\n if (nonNsAttr) {\n attributes.push(nonNsAttr);\n }\n });\n\n return attributes;\n};\n\nElementSerializer.prototype.parseGenericAttributes = function(element, attributes) {\n\n var self = this;\n\n forEach(attributes, function(attr) {\n\n try {\n self.addAttribute(self.nsAttributeName(attr.name), attr.value);\n } catch (e) {\n\n // eslint-disable-next-line no-undef\n typeof console !== 'undefined' && console.warn(\n `missing namespace information for <${\n attr.name\n }=${ attr.value }> on`, element, e\n );\n }\n });\n};\n\nElementSerializer.prototype.parseContainments = function(properties) {\n\n var self = this,\n body = this.body,\n element = this.element;\n\n forEach(properties, function(p) {\n var value = element.get(p.name),\n isReference = p.isReference,\n isMany = p.isMany;\n\n if (!isMany) {\n value = [ value ];\n }\n\n if (p.isBody) {\n body.push(new BodySerializer().build(p, value[0]));\n } else if (isSimpleType(p.type)) {\n forEach(value, function(v) {\n body.push(new ValueSerializer(self.addTagName(self.nsPropertyTagName(p))).build(p, v));\n });\n } else if (isReference) {\n forEach(value, function(v) {\n body.push(new ReferenceSerializer(self.addTagName(self.nsPropertyTagName(p))).build(v));\n });\n } else {\n\n // allow serialization via type\n // rather than element name\n var serialization = getSerialization(p);\n\n forEach(value, function(v) {\n var serializer;\n\n if (serialization) {\n if (serialization === SERIALIZE_PROPERTY) {\n serializer = new ElementSerializer(self, p);\n } else {\n serializer = new TypeSerializer(self, p, serialization);\n }\n } else {\n serializer = new ElementSerializer(self);\n }\n\n body.push(serializer.build(v));\n });\n }\n });\n};\n\nElementSerializer.prototype.getNamespaces = function(local) {\n\n var namespaces = this.namespaces,\n parent = this.parent,\n parentNamespaces;\n\n if (!namespaces) {\n parentNamespaces = parent && parent.getNamespaces();\n\n if (local || !parentNamespaces) {\n this.namespaces = namespaces = new Namespaces(parentNamespaces);\n } else {\n namespaces = parentNamespaces;\n }\n }\n\n return namespaces;\n};\n\nElementSerializer.prototype.logNamespace = function(ns, wellknown, local) {\n var namespaces = this.getNamespaces(local);\n\n var nsUri = ns.uri,\n nsPrefix = ns.prefix;\n\n var existing = namespaces.byUri(nsUri);\n\n if (!existing || local) {\n namespaces.add(ns, wellknown);\n }\n\n namespaces.mapPrefix(nsPrefix, nsUri);\n\n return ns;\n};\n\nElementSerializer.prototype.logNamespaceUsed = function(ns, local) {\n var namespaces = this.getNamespaces(local);\n\n // ns may be\n //\n // * prefix only\n // * prefix:uri\n // * localName only\n\n var prefix = ns.prefix,\n uri = ns.uri,\n newPrefix, idx,\n wellknownUri;\n\n // handle anonymous namespaces (elementForm=unqualified), cf. #23\n if (!prefix && !uri) {\n return { localName: ns.localName };\n }\n\n wellknownUri = namespaces.defaultUriByPrefix(prefix);\n\n uri = uri || wellknownUri || namespaces.uriByPrefix(prefix);\n\n if (!uri) {\n throw new Error('no namespace uri given for prefix <' + prefix + '>');\n }\n\n ns = namespaces.byUri(uri);\n\n // register new default prefix <xmlns> in local scope\n if (!ns && !prefix) {\n ns = this.logNamespace({ uri }, wellknownUri === uri, true);\n }\n\n if (!ns) {\n newPrefix = prefix;\n idx = 1;\n\n // find a prefix that is not mapped yet\n while (namespaces.uriByPrefix(newPrefix)) {\n newPrefix = prefix + '_' + idx++;\n }\n\n ns = this.logNamespace({ prefix: newPrefix, uri: uri }, wellknownUri === uri);\n }\n\n if (prefix) {\n namespaces.mapPrefix(prefix, uri);\n }\n\n return ns;\n};\n\nElementSerializer.prototype.parseAttributes = function(properties) {\n var self = this,\n element = this.element;\n\n forEach(properties, function(p) {\n\n var value = element.get(p.name);\n\n if (p.isReference) {\n\n if (!p.isMany) {\n value = value.id;\n } else {\n var values = [];\n forEach(value, function(v) {\n values.push(v.id);\n });\n\n // IDREFS is a whitespace-separated list of references.\n value = values.join(' ');\n }\n\n }\n\n self.addAttribute(self.nsAttributeName(p), value);\n });\n};\n\nElementSerializer.prototype.addTagName = function(nsTagName) {\n var actualNs = this.logNamespaceUsed(nsTagName);\n\n this.getNamespaces().logUsed(actualNs);\n\n return nsName(nsTagName);\n};\n\nElementSerializer.prototype.addAttribute = function(name, value) {\n var attrs = this.attrs;\n\n if (isString(value)) {\n value = escapeAttr(value);\n }\n\n // de-duplicate attributes\n // https://github.com/bpmn-io/moddle-xml/issues/66\n var idx = findIndex(attrs, function(element) {\n return (\n element.name.localName === name.localName &&\n element.name.uri === name.uri &&\n element.name.prefix === name.prefix\n );\n });\n\n var attr = { name: name, value: value };\n\n if (idx !== -1) {\n attrs.splice(idx, 1, attr);\n } else {\n attrs.push(attr);\n }\n};\n\nElementSerializer.prototype.serializeAttributes = function(writer) {\n var attrs = this.attrs,\n namespaces = this.namespaces;\n\n if (namespaces) {\n attrs = getNsAttrs(namespaces).concat(attrs);\n }\n\n forEach(attrs, function(a) {\n writer\n .append(' ')\n .append(nsName(a.name)).append('=\"').append(a.value).append('\"');\n });\n};\n\nElementSerializer.prototype.serializeTo = function(writer) {\n var firstBody = this.body[0],\n indent = firstBody && firstBody.constructor !== BodySerializer;\n\n writer\n .appendIndent()\n .append('<' + this.tagName);\n\n this.serializeAttributes(writer);\n\n writer.append(firstBody ? '>' : ' />');\n\n if (firstBody) {\n\n if (indent) {\n writer\n .appendNewLine()\n .indent();\n }\n\n forEach(this.body, function(b) {\n b.serializeTo(writer);\n });\n\n if (indent) {\n writer\n .unindent()\n .appendIndent();\n }\n\n writer.append('</' + this.tagName + '>');\n }\n\n writer.appendNewLine();\n};\n\n/**\n * A serializer for types that handles serialization of data types\n */\nfunction TypeSerializer(parent, propertyDescriptor, serialization) {\n ElementSerializer.call(this, parent, propertyDescriptor);\n\n this.serialization = serialization;\n}\n\ninherits(TypeSerializer, ElementSerializer);\n\nTypeSerializer.prototype.parseNsAttributes = function(element) {\n\n // extracted attributes with serialization attribute\n // <type=typeName> stripped; it may be later\n var attributes = ElementSerializer.prototype.parseNsAttributes.call(this, element).filter(\n attr => attr.name !== this.serialization\n );\n\n var descriptor = element.$descriptor;\n\n // only serialize <type=typeName> if necessary\n if (descriptor.name === this.propertyDescriptor.type) {\n return attributes;\n }\n\n var typeNs = this.typeNs = this.nsTagName(descriptor);\n this.getNamespaces().logUsed(this.typeNs);\n\n // add xsi:type attribute to represent the elements\n // actual type\n\n var pkg = element.$model.getPackage(typeNs.uri),\n typePrefix = (pkg.xml && pkg.xml.typePrefix) || '';\n\n this.addAttribute(\n this.nsAttributeName(this.serialization),\n (typeNs.prefix ? typeNs.prefix + ':' : '') + typePrefix + descriptor.ns.localName\n );\n\n return attributes;\n};\n\nTypeSerializer.prototype.isLocalNs = function(ns) {\n return ns.uri === (this.typeNs || this.ns).uri;\n};\n\nfunction SavingWriter() {\n this.value = '';\n\n this.write = function(str) {\n this.value += str;\n };\n}\n\nfunction FormatingWriter(out, format) {\n\n var indent = [ '' ];\n\n this.append = function(str) {\n out.write(str);\n\n return this;\n };\n\n this.appendNewLine = function() {\n if (format) {\n out.write('\\n');\n }\n\n return this;\n };\n\n this.appendIndent = function() {\n if (format) {\n out.write(indent.join(' '));\n }\n\n return this;\n };\n\n this.indent = function() {\n indent.push('');\n return this;\n };\n\n this.unindent = function() {\n indent.pop();\n return this;\n };\n}\n\n/**\n * A writer for meta-model backed document trees\n *\n * @param {Object} options output options to pass into the writer\n */\nexport function Writer(options) {\n\n options = assign({ format: false, preamble: true }, options || {});\n\n function toXML(tree, writer) {\n var internalWriter = writer || new SavingWriter();\n var formatingWriter = new FormatingWriter(internalWriter, options.format);\n\n if (options.preamble) {\n formatingWriter.append(XML_PREAMBLE);\n }\n\n var serializer = new ElementSerializer();\n\n var model = tree.$model;\n\n serializer.getNamespaces().mapDefaultPrefixes(getDefaultPrefixMappings(model));\n\n serializer.build(tree).serializeTo(formatingWriter);\n\n if (!writer) {\n return internalWriter.value;\n }\n }\n\n return {\n toXML: toXML\n };\n}\n\n\n// helpers ///////////\n\n/**\n * @param {Moddle} model\n *\n * @return { Record<string, string> } map from prefix to URI\n */\nfunction getDefaultPrefixMappings(model) {\n\n const nsMap = model.config && model.config.nsMap || {};\n\n const prefixMap = {};\n\n // { prefix -> uri }\n for (const prefix in DEFAULT_NS_MAP) {\n prefixMap[prefix] = DEFAULT_NS_MAP[prefix];\n }\n\n // { uri -> prefix }\n for (const uri in nsMap) {\n const prefix = nsMap[uri];\n\n prefixMap[prefix] = uri;\n }\n\n for (const pkg of model.getPackages()) {\n prefixMap[pkg.prefix] = pkg.uri;\n }\n\n return prefixMap;\n}"],"names":["parseNameNS","assign","coerceType","forEach","find","isSimpleType","Moddle","SaxParser","isString","filter","has","findIndex"],"mappings":"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