-
Notifications
You must be signed in to change notification settings - Fork 5
XMLMarshaller
XMLMarshaller is a means for generating valid XML according to a given XML Schema using it as a template to be filled in with data from plain Objects.
The conception is based on EclipseLink MOXy's Marshaller features related to JSON Documents.
// const fs = require ('node:fs')
// out = fs.createWriteStream ('out.xml')
const xs = new XMLSchemata ('wsdl_related_stuff.xsd')
const m = xs.createMarshaller (localName, namespaceURI
//, {
// out,
// decl: {encoding: 'UTF-8', standalone: 1},
// space: 2,
// attrSpace: 1,
// EOL: '\n',
// level: 0,
// encodeLineBreaks: false,
// })
)The 3rd, optional, argument is the bag of options for:
- either an XMLStreamPrinter instance (with the
outprovided); - or XMLPrinter (without one).
// no `out` option: appending a string, the result is available immediately
const xml = m.stringify (data
//, {declaration : {encoding: 'UTF-5'}}
)
// `out` option set: writing to a stream
await new Promise ((ok, fail) => {
out.on ('error', fail)
out.on ('close', ok)
m.stringify (data
//, {declaration : {encoding: 'UTF-5'}}
)
})Based on whether the out option was passed to the constructor, the stringify () method's semantics differs sligthtly:
- with no
outoption set, the serialization is totally synchronous and the resulting XML is thestringify ()return value; - when the
outoption is provided, it must be a Writable stream where the XML content is written to, sostringify ()returnsundefined(unless an error is thrown) and it's up to the API consumer to watch for the'finish'or'close'event.
Nullish values are represented either with no text at all (for minOccurs="0") or with xsi:nil attribute, according to the schema definition.
For all other values, see XSSimpleType.
Attribute only elements are naturally mapped from scalar valued plain objects:
{Order: {amount: 1, price: 2.34}} // <Order amount="1" price="2.34"/>Text only child elements are normally represented by scalar properties of data objects:
{Outer: {Inner: 123}} // <Outer><Inner>123</Inner></Outer>But how to represent data for elements with both attributes and text content? In this case, the text must be presented as a null named pseudo attribute:
{Request: {Id: 1, null: 'HELO'}} // <Request Id="1">HELO</Request>Sometimes, the element name is not enough to choose the right complex type, you have to point it explicitly with the xsi:type attribute. In xml-toolkit, Symbol.for ('type') can be used in such situations:
AppData: {
data: {
[Symbol.for ('type')]: 'TheSpecialRequest',
id: 123456,
count: 1,
page: 1
}
}Some schemata (like SOAP 1.1) contain any and anyAttribute wildcards corresponding to XML fragments of unknown structure.
For stringify to fill in such a wildcard, the content must be presented as a special object with null key is provided:
xs.stringify ({
Envelope: {
Body: { // contains xs:any, xs:anyAttribute
null: { // cannot be localName, so no possible confilct here
'<someRequest>CODE</someRequest>': // raw XML content to be injected as xs:any
{Id: 1 /*, ...*/} // "any" attributes key/value pairs
}},
}
}
)yields
<ns0:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/">
<ns0:Body Id="1"><someRequest>CODE</someRequest></ns0:Body>
</ns0:Envelope>In application code, such values may be produced with the XMLSchemata.any convenience method.