-
Notifications
You must be signed in to change notification settings - Fork 3
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.xml
First, 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 XMLNode
s.
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 .xml
s 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:
-
.isCharacters
field (same as.type === 'Characters'
, but less error prone); -
.parent
reference (pointing to the enclosingXMLNode
)- the latter's
.localName
.
- the latter's