I need to update my xml with a tag in every element

I have a xml like this:

<LangPref>ENGLISH</LangPref>
<POI>
  <POINum>1024211680</POINum>
<POI>

I just need to add namespace like below

<ns1:LangPref>ENGLISH</ns1:LangPref>
<ns1:POI>
  <ns1:POINum>1024211680</ns1:POINum>
</ns1:POI>

Any suggestion on the best way to do it?

0 3 539
3 REPLIES 3

You can get close to doing that with an XSL, or with a JavaScript using E4X (I talked about these options in a recent answer to a different question of yours). But not exactly.

The desired result you showed is not well-formed XML. One reason is, there is a namespace prefix used (ns1:) but that prefix is not declared with an xmlns attribute.  Another reason is, there is no single root element.  (Maybe you are intending to show only a fragment of the desired output XML.) It's not possible to get Apigee's XML processing logic (XSL or JS and E4X) to accept as input, the first thing you showed, and it's not possible to get them to emit as output, something like what you showed in the second block. Those things in Apigee will accept and emit only well-formed XML. They don't accept or emit fragments of XML.  You would have to use string manipulation, not XML processing, to generate something like what you showed in Apigee.

If your requirement is that you want to inject that fragment into a larger document, and the larger document includes the namespace declaration for the  ns1 prefix, then, ok, we can talk about configuring Apigee to do something like that.  Or maybe you have an existing complete XML document with that fragment, and you want to modify that document to insert namespace prefixes. Or maybe you are thinking something else.

So maybe you can reframe your question, add more context?  What is the input?  what existing XML document do you have? (show the complete document)  what is the complete desired output? and with that extra context we'll see if we can help.

Thanks, Exact the second case you explained in your answer I want. I have an existing XML document with all required XML tags and namespace declaration. I need to inject this custom fragment into that XML document.

Sorry about the delay, the holidays intervened for me! I think I have an example that might help.

If I were doing what you describe, and knowing that you don't want to use XSL, I would use E4X. You didn't show me the "outer" existing document. So I will just contrive one.

I will use this as the original document:

 

<RootElement xmlns="urn:086360F0-781E-41E6-8F8F-41A8025EDD01" xmlns:ns1="urn:0000-0000-0001">
  <Emplid>123</Emplid>
  <LocationId>456</LocationId>
  <Profile>
    <ns1:Status>active</ns1:Status>
  </Profile>
</RootElement>

 

And the goal is to insert a few nodes under the "Profile" element.

 

<RootElement xmlns="urn:086360F0-781E-41E6-8F8F-41A8025EDD01" xmlns:ns1="urn:0000-0000-0001">
  <Emplid>123</Emplid>
  <LocationId>456</LocationId>
  <Profile>
    <ns1:Status>active</ns1:Status>
    <!-- goal: insert nodes here -->
  </Profile>
</RootElement>

 

I can do that with a few lines of JS + E4X. Just a reminder: E4X is "an interface" within JavaScript for manipulating XML. So basically I'm writing a JavaScript callout for Apigee, and taking advantage of that interface within the JS code. With this code:

 

var message = context.getVariable(properties.sourceMessage);
if (message && message.content) {
  var root = new XML(message.content);
  var ns0 = new Namespace(properties.xmlns0);
  var ns1 = new Namespace(properties['xmlns1-prefix'], properties.xmlns1);

  var profile = root.ns0::Profile;

  // insert two new nodes under Profile
  var fragment1 = new XML('<LangPref>' + properties.langPref + '</LangPref>');
  fragment1.setNamespace(ns1);
  profile.appendChild(fragment1);

  // This second node has a child node
  var fragment2 = new XML('<POI/>')
  fragment2.setNamespace(ns1);

  var fragment3 = new XML('<POINum>' + properties.POINum + '</POINum>');
  fragment3.setNamespace(ns1);
  fragment2.appendChild(fragment3);
  profile.appendChild(fragment2);

  // replace the content of the message with the modified version
  message.content = root.toXMLString();
}

 

I can generate this output XML document:

 

<RootElement xmlns="urn:086360F0-781E-41E6-8F8F-41A8025EDD01" xmlns:ns1="urn:0000-0000-0001">
  <Emplid>123</Emplid>
  <LocationId>456</LocationId>
  <Profile>
    <ns1:Status>active</ns1:Status>
    <ns1:LangPref>English</ns1:LangPref>
    <ns1:POI>
      <ns1:POINum>1024211680</ns1:POINum>
    </ns1:POI>
  </Profile>
</RootElement>

 

...which was the goal.  Attached please find the working API Proxy.

This isn't exactly what you wanted I guess, but you can probably modify what I provided to do what you need.