Skip to Content
Author's profile photo Former Member

SAP PI 7.1 Mapping Enhancements Series: Copy XML Subtree

Introduction:

CopyXML is a new feature in the Message Mapping tool of PI 7.1. This feature can be used when we wish to copy an XML subtree from the source to target, exactly as is. Why is this so special? Well, by using this tool, we do not need to define the target elements and only one elemet-to-element mapping is required, no matther how many elements are in the subtree.

In this blog, I will discuss on how to use this feature and when the feature will not work or cannot be used.

Using CopyXML:

Let’s take a look at the following mapping requirement:

We have a simple customer order document. The source has an address; the target has a billing address and a delivery address. We want to copy all the elements in “address” of the source to “BillingAddress” and “DeliveryAddress” of the target.

image

As you will notice, the target does not have all the elements defined.

Assign the Mappings:

  1. Double-click on “BillingAddress” of the target, and double-click on the “address” of the source, just as in the previous releases when we want to map from 1 element to another.
  2. Drag a direct mapping line between these 2 elements.
  3. Right-click on “address” and select “Return as XML” in the dropdown menu.

    image

  4. Repeat the steps to map “address” to “DeliveryAddress”.

    image

Verifying the mapping:

Below is the result of the mapping. All the elements in “address” have been mapped to “BillingAddress” and “DeliveryAddress”.

image

As you can see, the complete subtree of “address” is copied under “BillingAddress” and “DeliveryAddress”. And, we did NOT define any of the “address” elements in “BillingAddress” and “DeliveryAddress”.

But, what happens when…

As you will notice, under “BillingAddress”, there is an element “address”:

image

Now, let us map something to it. It does not matter what, any mapping will do. In this case, we will just map “Street” to it.

image

Let’s us take a look at the result of this mapping.

image

The “address” subtree was not copied to “BillingAddress”. So, when there is any mapping done to any of the sub-element of the target node, that mapping will take priority and void the CopyXML done to that target.

Assigned Tags

      13 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Henrique Pinto
      Henrique Pinto

      Hi Bill,<br/><br/>quick question: what about XML namespaces?<br/><br/>If in the target side we have different namespaces, that will insert a huge problem and the target application won't be able to understand the extra fields...<br/><br/>From my point of view, this works like <copy-of> functionality in XSLT, is that so?<br/><br/>Best regards,<br/>Henrique.

      Author's profile photo Former Member
      Former Member
      Hello Henrique,

      Actually when i first saw that feature, i thought of the xsl copy-of, too 🙂
      Happily it doesn't have the same behaviour, it doesn't copy the namespace, just the plain xml tags.

      Best regards
                Sebastian

      Author's profile photo Former Member
      Former Member
      Blog Post Author
      Hi Henrique,
      A changed XML namespace can also be resolved using this tool.

      Unlike XSLT's "copy-of", the namespace in the mapping program is changed to the new one.

      Regards,
      Bill

      Author's profile photo Henrique Pinto
      Henrique Pinto
      But does the developer have control on how/when to change the namespaces? Sometimes, it's not desirable to do it...

      Allied with escaping/unescaping standard functions, this would eliminate 99% of the needs for code based (java & xslt) mappings.

      Regards,
      Henrique.

      Author's profile photo Former Member
      Former Member
      Blog Post Author
      Hi Henrique,
      Unfortunate, for your question, I don't think it will take place of code-based mappings.

      This is a design-time tool, to resolved the mapping when the target and/or source XSD (msg types) have changed after the mapping has already been done. 

      For example, this is to avoid re-doing the mapping if the namespace changed in either the source or target's message type.

      Regards,
      Bill

      Author's profile photo Former Member
      Former Member
      Hi Bill,

      If I have Continent node instead address in target under BillingAddress and want to use address + Continent in my target how will do it. I will map continent from some other header other address node from source. is it possiable or copy-xml will not work in this case

      Thanks
      Sreeram.G.Reddy

      Author's profile photo Former Member
      Former Member
      Blog Post Author
      Hi,
      Copy-XML can only copy the children elements exactly as is, no change is possible.  If any of the child element requires a different mapping, then copy-xml cannot be used.

      Regards,
      Bill

      Author's profile photo Sunil Mavachee
      Sunil Mavachee
      Hi bill,

      The blog is really good one for pi guys,

      Expected more from your experience.

      Thanks and Regards,

      Sunil Mavachee

      Author's profile photo Former Member
      Former Member
      This is a nice feature
      Author's profile photo Former Member
      Former Member
      Nice blog Bill, very clear.

      I was hoping to use this method to copy an entire message to another copy of itself. I have a mapping with message MSG as both source and target, and I have mapped the source root element to the target root element, and selected "Return as XML" on the source element brick.

      However, my schema has required child elements (1..1) in the subtree, so the mapping fails as it does not find a mapping for those target elements.

      I know I can use the "Map selected fields and substructures..." toolbar button to quickly map each identical field betwen source and target, but if the schema chanegs I have to fix the mapping. So I was hoping to use your technique to avoid this.

      Any thoughts on how to use your ideas for this scenario?

      Thanks,

      RBL

      Author's profile photo Former Member
      Former Member
      Blog Post Author
      Hi,
      I don't think you can do what you want.  Is it possible to change the XSD of the source?  That would solve your problem.

      If not, maybe you can have another mapping program before this, where the target map contains the XSD with optional fields.

      Regards,
      Bill

      Author's profile photo Former Member
      Former Member

      hi William,

      I have a similar requirement as above, in which i have a source and target the same structures. However, while i am copying source to target, i also have a requirement to create one attachment each for every source node occurence. Please find below a sample case of my requirement :-

      Source:-

      <Messages>

      <Message1>

      <SBDH number=1">...</>

      <SBDH number=2">...</>

      <SBDH number=3">...</>

      UDf used :-

      ----- 

      GlobalContainer globalContainer = container.getGlobalContainer();
      OutputAttachments outputAttachments = globalContainer.getOutputAttachments() ;

      AbstractTrace trace = container.getTrace();
      String attachmentName = "attachment";
      Attachment newopAttachment = null;

      try
      {

      var1=var1.replaceAll("><",">\n<");
      attachmentName = "attachment" + cnt;
      newopAttachment = outputAttachments.create((attachmentName), var1.getBytes("UTF-8"));
      outputAttachments.setAttachment(newopAttachment);

      cnt=c

      nt+1;
      }
      catch (Exception e)
      {  
      trace.addInfo("ever reaching trace");
            e.printStackTrace(); 
      }

      return "1";

      -------

      Please note that cnt is maintained as a global variable, and the above udf is a single value udf.

      input SBDH- return as XML - > Splitbyvalue - > UDF - > Message1.

      The issue is when the output comes in runtime, i get it as below :-

      MainDocument ( application/xml ) of SBDH number = 1

      SubMainDocument ( text/xml ) of SBDH number = 1

      SubAttachment ( application/xml )of SBDH number = 1

      MainDocument ( application/xml ) of SBDH number = 2

      SubMainDocument ( text/xml ) of SBDH number = 2

      SubAttachment ( application/xml )of SBDH number = 1

      MainDocument ( application/xml ) of SBDH number = 3

      SubMainDocument ( text/xml ) of SBDH number = 3

      SubAttachment ( application/xml )of SBDH number = 1

      As you can see all attachments are the same.. i dont understand if it is a context problem or something with the return as xml

      Please help.

      Regards,

      ninu

      Author's profile photo Former Member
      Former Member
      You can right click on the required fields in the target and select 'Disable Field'. This will let you bypass the requirement of mapping the required fields.

      praveen