Composing XML Messages from Fragments¶
When the outbound document is large enough that building it as one templated string gets unwieldy, a CDA document with several sections, a SOAP envelope wrapping a payload, any case where the parts are easier to build separately. Assemble each fragment as its own XML message and graft them together with addChildMessage. Each fragment can be evaluated, validated, or built by its own helper function in isolation, and the final assembly step is a structural operation against parsed XML rather than a string splice that depends on placeholder text surviving template evaluation.
addChildMessage(parentNodePath, childMessage) appends the child's root element as a new child of the node found at parentNodePath. It is the only XML message method that takes another message as its argument. setNode and friends take a String value, which is for setting a node's text content, not for grafting a subtree.
Core pattern¶
The working message is the parent, typically an XML message the channel is building up, or one created with qie.createXMLMessage('<Report><sections/></Report>') at the top of the script. Build each fragment as an XML string, parse it, and append it under a container element.
var demographics = '<patient>\n' +
' <id>123456</id>\n' +
' <firstName>Jane</firstName>\n' +
' <lastName>Doe</lastName>\n' +
' <dateOfBirth>1985-04-12</dateOfBirth>\n' +
' <gender>F</gender>\n' +
' <address>\n' +
' <street>123 Main St</street>\n' +
' <city>Metropolis</city>\n' +
' <state>NY</state>\n' +
' <postalCode>10001</postalCode>\n' +
' </address>\n' +
'</patient>';
var results = '<results>\n' +
' <result>\n' +
' <testName>COVID-19</testName>\n' +
' <status>Negative</status>\n' +
' </result>\n' +
'</results>';
message.addChildMessage('/Report/sections', qie.parseXMLString(demographics));
message.addChildMessage('/Report/sections', qie.parseXMLString(results));
After the two appends, the document looks like:
<Report>
<sections>
<patient>
<id>123456</id>
...
</patient>
<results>
<result>...</result>
</results>
</sections>
</Report>
addChildMessage imports the child's root element under the target node, so each fragment string should be a single root element: <patient>...</patient>, not <patient/><results/> and not bare text content.
Alternative: addChild / addChildBefore / addChildAfter¶
These three take a String value, and when the value starts with < it gets parsed and grafted in as child nodes. Use them when the inserted content needs a wrapper element with a fixed name, or when the natural insertion point is "as a sibling next to an existing node" rather than "as a child of a container."
That produces:
Note the new <demographics> wrapper around the fragment. addChild and friends create an element with the given nodeName and graft the parsed value inside it. addChildMessage does not add a wrapper; the fragment's own root element becomes the child.
There is one collapse case worth knowing: when nodeName matches the root element name of the value XML, the wrapper is dropped.
Since demographics starts with <patient>, that produces a single <patient>...</patient> sibling after <sections>, not <patient><patient>...</patient></patient>. Match the names when you do not want a wrapper; differ them when you do.
addChild(nodePath, nodeName, value, index*). Appends (or inserts atindex) as a child of the node atnodePath.addChildBefore(nodePath, nodeName, value). Inserts as a sibling before the node atnodePath.addChildAfter(nodePath, nodeName, value). Inserts as a sibling after the node atnodePath.
Append, not replace¶
addChildMessage appends a child under the target node. There is no "replace this placeholder element" operation on the XML message model. Two consequences:
- Build the parent so the target node is a container (
<sections/>,<structuredBody/>,<entries/>) and letaddChildMessageadd real children to it. Do not put placeholder elements like<section id="demographics-here"/>inside the container expecting them to be replaced. They are still there after the appends, sitting next to the appended fragments. - Calling
addChildMessagetwice with the same target appends twice. To rebuild a section after a downstream failure, either start with a fresh parent message or remove the appended children first withremoveFirstNode/removeLastNode/removeAllNodes.
Constraints¶
- The parent message must be non-empty. Build it from a parsed string or
qie.createXMLMessage('<Root/>'), not from an uninitializedMessageModel. - The child must be an XML message model. JSON or CSV messages cannot be appended into XML this way.
- The target
nodePathmust resolve to exactly one node. If it does not,addChildMessagethrowsNode not found: <path>.
When to keep using string templates¶
If the document is small and the placeholders are stable, the Build a New Output Message recipe's qie.evaluateTemplate approach is simpler. Reach for XML composition when:
- The fragments are independently testable (each has its own helper or its own template).
- You want the assembly step to fail with
Node not found: ...if the parent shape changes, instead of silently leaving a literal%%SECTION%%token in the output. - You're already parsing the result for downstream XML operations (namespace fixes, attribute manipulation, prolog) and would have to parse the templated string anyway.
See Standard QIE Objects for the full XML message model: addChildMessage, addChild, addChildBefore, addChildAfter, removeFirstNode / removeAllNodes, addProlog, and namespace handling are all on the same object.