When you use the .asXML thing, you get an XML object. The behavior of that XML object is defined as a part of larger set of xml capabilities, under the umbrella of E4X, which stands for EcmaScript for XML. E4X was a standard extension to EcmaScript (aka JavaScript) for a while, but then later was deprecated. It is still supported in the Rhino JS engine that Apigee uses, still supported in Apigee.
There is a way to do what you want using E4X, within a JS callout in Apigee. Unfortunately because E4X was deprecated from mainline Javascript, the documentation for the capability can be difficult to find. Sometimes it can be difficult to figure out how you should do a particular thing. But I can show you.
var message = context.getVariable('name_of_source_message');
if (message && message.content) {
var xml = new XML(message.content);
var ns1 = new Namespace('ns1','urn://24F9C86E-D207-4049-850B-02C48F138AA1');
var soap = new Namespace('soap','http://www.w3.org/2003/05/soap-envelope');
var body = xml.soap::Body;
// modify the text value of a specific node
var amountTextNode = body.ns1::someMethod.ns1::Status.ns1::amount.text();
amountTextNode.parent().setChildren('200');
// insert a new element
var studentNode = body.ns1::someMethod.ns1::Status.ns1::student;
var fragment = new XML('<id>xx123</id>');
fragment.setNamespace(ns1);
studentNode.appendChild(fragment);
// replace the content of the message with the modified version
message.content = xml.toXMLString();
}
// get student id
var studentid = "xx123";
// read soap xml from request payload
var message = context.getVariable("request.content");
// modify request payload before sending to backend server
if (message && message.content) {
var xml = new XML(message.content);
var soapenv = new Namespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
var urn = new Namespace("urn", "urn:24F9C86E-D207-4049-850B-02C48F138AA1");
var someMethod = xml.soapenv::Body.urn::SomeMethod;
// modify the text value of a specific node
var amountTextNode = someMethod.Amount.text();
amountTextNode.parent().setChildren("200");
// insert new element
var studentNode = someMethod.Student;
var fragXML = "<ID>" + studentid + "<ID>";
var fragment = new XML(fragXML);
studentNode.appendChild(fragment);
// replace the content of the message with the modified version
message.content = xml.toXMLString();
}
There is no error, but the payload does not get updated.
yes, you need to modify the code that I showed you.
The code I wrote works with MY XML. It won’t work with YOUR XML. Your XML has different elements, different namespaces. For example, your Student node has no XML namespace. (You noticed that). As another example, adding a namespace-qualified attribute, like xsi:type="xsd:string", you need to use some specific syntax.
This worked for me.
var message = context.getVariable(properties.sourceMessage);
var newStudentId = 'xx123';
if (message && message.content) {
var xml = new XML(message.content);
// get references to the namespaces uses in this document
var ns1 = new Namespace('ns1','urn:24F9C86E-D207-4049-850B-02C48F138AA1');
var soap = new Namespace('soap','http://schemas.xmlsoap.org/soap/envelope/');
var someMethod = xml.soap::Body.ns1::SomeMethod;
// modify the text value of a specific node
var amountTextNode = someMethod.Amount.text();
amountTextNode.parent().setChildren('200');
// insert a new node under Student
var studentNode = someMethod.Student;
var fragment = new XML('<ID>' + newStudentId + '</ID>');
var xsi = new Namespace('xsi','http://www.w3.org/2001/XMLSchema-instance');
fragment.addNamespace(xsi);
fragment.@xsi::type = 'xsd:string';
studentNode.appendChild(fragment);
// replace the content of the message with the modified version
message.content = xml.toXMLString();
}