-
Notifications
You must be signed in to change notification settings - Fork 4
Use Case: Patching XML
Consider the following XML given as a string named xmlSource:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<GetResponseResponse xmlns="urn://some-schema" xmlns:ns0="urn://another-schema">
<ResponseMessage>
<Response>
<OriginalMessageId>00000000-0000-0000-0000-000000000000</OriginalMessageId> <!-- to be substituted -->
<SenderProvidedResponseData>
<!-- and so on -->The goal is to obtain the XML text representing the same document with OriginalMessageId's content replaced with a given id.
const {XMLReader} = require ('xml-toolkit')
let xmlResult = ''; for await (const node of new XMLReader ().process (xmlSource)) xmlResult +=
node.isCharacters && node.parent.localName === 'OriginalMessageId' ? id :
node.xmlFirst, an XMLReader instance is created. This is a SAX style parser.
The .process (xmlSource) call returns the same object, but emitting the sequence of XMLNodes (in xml-toolkit, it's a SAXEvent's subclass) representing parts of the input XML document.
XMLReader is an object mode Readable stream, of XMLNodes.
In particular, they are available to read with a for await loop, as every Readable stream provides an asynchronous iterator.
Each XMLNode has an xml field: the string representing that node. So, by concatenating all .xmls we'll reconstruct the input XML text.
The last step to solve the problem is to substitute the .xml value of one text node with the arbitary value. The node to replace is detected with:
-
.isCharactersfield (same as.type === 'Characters', but less error prone); -
.parentreference (pointing to the enclosingXMLNode)- the latter's
.localName.
- the latter's