on 2023 May 31 12:46 PM
Hi Experts,
I want to store an XPath in the property using a content modifier for the attached Payload.
I tried the below, but the response looked weird as below.
So, I have changed the Data Type to java.lang.Object . Now, I am able to capture the data in the property.
Not sure, If I am overlooking or missing something.
Any leads/solutions will be really helpful.
Regards,
Pavan
Hi Pavan
I think your case is a good fit with the Filter step.
But if you use data type "org.w3c.dom.Node", you can achieve what you are trying to do here. Create a property with that type using one of your XPath expressions. You can then replace the message body with that property in a Content Modifier later on.
Regards,
Morten
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Dear Pavan,
I think you can use either of these below Data Types with xpath : "/CustomPayload/TransformedData" and "/CustomPayload/SourceData" and it will give you exact same results. But each Data Type will create differnt kinds of Saxon impl class (Node, NodeList and NodeInfo) objects.
After the first contentmodifier whenever you want you can just move those objects from properties to body and you are done. Then you can use them for mapping.
Test -
If you want to use them in groovy then you need to use appropriate class to access them (as they are objects of impl classes of NodeList, Node and NodeInfo). Here i am giving an example of if you have defined data type as "org.w3c.dom.NodeList"
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import javax.xml.transform.OutputKeys
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerException
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult;
import net.sf.saxon.dom.DOMNodeList;
def Message processData(Message message) {
def properties = message.getProperties();
value = properties.get("first");
message.setProperty("firstString", nodeListToString(value))
return message;
}
private static String nodeListToString(DOMNodeList nodes) throws TransformerException {
DOMSource source = new DOMSource();
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
for (int i = 0; i < nodes.getLength(); ++i) {
source.setNode(nodes.item(i));
transformer.transform(source, result);
}
return writer.toString();
}
Results -
Thanks,
Asu
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi mnw,
Thanks for the response.
I would like to store 2 XPaths for now (maybe more in the future) and pass them to the next steps for further processing which involves mapping where the mapping considers one of these properties as input.
Tried to store the data as properties using the below Groovy as well. But, no luck yet.
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.util.*;
def Message processData(Message message) {
def xml = message.getBody(String.class)
def completeXml= new XmlSlurper().parseText(xml)
def sd = completeXml.RetryPayload.'**'.findAll { node-> node.name() == 'SourceData'}*.text()
def td = completeXml.RetryPayload.'**'.findAll { node-> node.name() == 'TransformedData'}*.text()
message.setProperty("SourceData", sd)
message.setProperty("TransformedData", td)
return message
}<br>
Regards,
Pavan
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Pavan,
You can use Node or Nodelist as Data Type in your Exchange Property to preserve the XML tree of the TransformedData node. Using the String data type will only give you the values of the underlying nodes, as you experienced.
See here for examples: https://blogs.sap.com/2017/06/01/sap-cloud-platform-integration-content-filter-in-detail/
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi willem.pardaens,
Thanks for the response.
I would like to store 2 XPaths(maybe more in the future) and pass them to the next steps for further processing which involves mapping where the mapping considers once of these properties as input. So Filtering the step is not ideal for me :(.
Regards,
Pavan
Could you provide us with a sample XML input, as well as intended output? From your description it is difficult to understand what you are trying to do.
InputPayload:
<RetryPayload>
<SourceData>
<Z_SDSL_REPLICATE_SALES_ORDER>
<REFUND_GIFT_CARD/>
<SALES_ORDER_BILLING_ADDRESS>
<CUST_USER_NAME/>
<CARE_OF/>
</SALES_ORDER_BILLING_ADDRESS>
<SALES_ORDER_CUSTOMER>
<CUSTOMERID>1234565432</CUSTOMERID>
<GUEST>0</GUEST>
<NAME>fra fra</NAME>
<FIRST_NAME>fra</FIRST_NAME>
<LAST_NAME>fra</LAST_NAME>
</SALES_ORDER_CUSTOMER>
<SALES_ORDER_HEADER>
<VKTYP>CC</VKTYP>
<TXT_PAYMENT_CARD>VISA ************1111</TXT_PAYMENT_CARD>
<TOTAL_DISCOUNTS>0.0</TOTAL_DISCOUNTS>
<ABFAPIAOREQUEST>0</ABFAPIAOREQUEST>
<AB_INVOICE>0</AB_INVOICE>
<UPDATEFLAG>I</UPDATEFLAG>
<DELIVERY_COST>0</DELIVERY_COST>
<PAYMENT_FEE>0.0</PAYMENT_FEE>
<CURRENCY>GBP</CURRENCY>
<ORDER_LANGUAGE>en_GB</ORDER_LANGUAGE>
<ZZCORPORATEBRANDID>0</ZZCORPORATEBRANDID>
<ZZBILLING_BLOCK>0</ZZBILLING_BLOCK>
<ZZORDER_VERSION>14</ZZORDER_VERSION>
<SPLIT_ORDER>1</SPLIT_ORDER>
<CONS_SHIPPING_FEE_SWITCH>0</CONS_SHIPPING_FEE_SWITCH>
</SALES_ORDER_HEADER>
<VOUCHER/>
</Z_SDSL_REPLICATE_SALES_ORDER>
</SourceData>
<TransformedData>
<ns2:ZLO_REPLICATE_SALES_ORDER_V2G
xmlns:ns2="urn:sap-com:document:sap:rfc:functions">
<SALES_ORDER_CUSTOMER>
<CUSTOMERID>1234565432</CUSTOMERID>
<NAME>fra fra</NAME>
<FIRST_NAME>fra</FIRST_NAME>
<LAST_NAME>fra</LAST_NAME>
<TITLE/>
<PERSONAL_LEGAL_NO/>
<TEL_NO/>
<GUEST>0</GUEST>
<CODICE_DESTINARIO/>
<CERTIFIED_EMAIL/>
</SALES_ORDER_CUSTOMER>
<SALES_ORDER_HEADER>
<RETURN_ORDERID/>
<COMPENSATION_ID/>
<DOC_DATE>2023-05-10</DOC_DATE>
<VKTYP>CC</VKTYP>
<ZZPAYTYPE/>
<TXT_PAYMENT_CARD>VISA ************1111</TXT_PAYMENT_CARD>
<TOTAL_DISCOUNTS>0.0</TOTAL_DISCOUNTS>
<ABFAPIAOREQUEST>0</ABFAPIAOREQUEST>
<ABSTAFFCARDNUMBER/>
<CONSIGNMENT_ID/>
<PICKUP_POINT_FLAG/>
</SALES_ORDER_HEADER>
<VOUCHER/>
</ns2:ZLO_REPLICATE_SALES_ORDER_V2G>
</TransformedData>
</RetryPayload>
Output in Property Name (SourceData):
<SourceData>
<Z_SDSL_REPLICATE_SALES_ORDER>
<REFUND_GIFT_CARD/>
<SALES_ORDER_BILLING_ADDRESS>
<CUST_USER_NAME/>
<CARE_OF/>
</SALES_ORDER_BILLING_ADDRESS>
<SALES_ORDER_CUSTOMER>
<CUSTOMERID>1234565432</CUSTOMERID>
<GUEST>0</GUEST>
<NAME>fra fra</NAME>
<FIRST_NAME>fra</FIRST_NAME>
<LAST_NAME>fra</LAST_NAME>
</SALES_ORDER_CUSTOMER>
<SALES_ORDER_HEADER>
<VKTYP>CC</VKTYP>
<TXT_PAYMENT_CARD>VISA ************1111</TXT_PAYMENT_CARD>
<TOTAL_DISCOUNTS>0.0</TOTAL_DISCOUNTS>
<ABFAPIAOREQUEST>0</ABFAPIAOREQUEST>
<AB_INVOICE>0</AB_INVOICE>
<UPDATEFLAG>I</UPDATEFLAG>
<DELIVERY_COST>0</DELIVERY_COST>
<PAYMENT_FEE>0.0</PAYMENT_FEE>
<CURRENCY>GBP</CURRENCY>
<ORDER_LANGUAGE>en_GB</ORDER_LANGUAGE>
<ZZCORPORATEBRANDID>0</ZZCORPORATEBRANDID>
<ZZBILLING_BLOCK>0</ZZBILLING_BLOCK>
<ZZORDER_VERSION>14</ZZORDER_VERSION>
<SPLIT_ORDER>1</SPLIT_ORDER>
<CONS_SHIPPING_FEE_SWITCH>0</CONS_SHIPPING_FEE_SWITCH>
</SALES_ORDER_HEADER>
<VOUCHER/>
</Z_SDSL_REPLICATE_SALES_ORDER>
</SourceData>
Output in Property Name(TransformedData):
<TransformedData>
<ns2:ZLO_REPLICATE_SALES_ORDER_V2G
xmlns:ns2="urn:sap-com:document:sap:rfc:functions">
<SALES_ORDER_CUSTOMER>
<CUSTOMERID>1234565432</CUSTOMERID>
<NAME>fra fra</NAME>
<FIRST_NAME>fra</FIRST_NAME>
<LAST_NAME>fra</LAST_NAME>
<TITLE/>
<PERSONAL_LEGAL_NO/>
<TEL_NO/>
<GUEST>0</GUEST>
<CODICE_DESTINARIO/>
<CERTIFIED_EMAIL/>
</SALES_ORDER_CUSTOMER>
<SALES_ORDER_HEADER>
<RETURN_ORDERID/>
<COMPENSATION_ID/>
<DOC_DATE>2023-05-10</DOC_DATE>
<VKTYP>CC</VKTYP>
<ZZPAYTYPE/>
<TXT_PAYMENT_CARD>VISA ************1111</TXT_PAYMENT_CARD>
<TOTAL_DISCOUNTS>0.0</TOTAL_DISCOUNTS>
<ABFAPIAOREQUEST>0</ABFAPIAOREQUEST>
<ABSTAFFCARDNUMBER/>
<CONSIGNMENT_ID/>
<PICKUP_POINT_FLAG/>
</SALES_ORDER_HEADER>
<VOUCHER/>
</ns2:ZLO_REPLICATE_SALES_ORDER_V2G>
</TransformedData>
I tried changing the data type from "java.lang.String" to "Node" and from "java.lang.String" to "Nodelist"
Both didn't work, in fact, deployment failed with the below error.
Error Message:
**********************************
[CONTENT][CONTENT_DEPLOY][RuntimeError] : {"message":"EXCEPTION","parameters":["org.apache.camel.FailedToCreateRouteException: Failed to create route Process_1 at: >>> SetProperty[TransformedData, xpath{//TransformedData}] <<< in route: Route(Process_1)[[From[direct:Test_Message_Steps_TimerEventD... because of java.lang.ClassNotFoundException: Nodelist"],"childMessageInstances":[{"message":"CAUSE","parameters":["org.apache.camel.RuntimeCamelException: java.lang.ClassNotFoundException: Nodelist"],"childMessageInstances":[{"message":"CAUSE","parameters":["java.lang.ClassNotFoundException: Nodelist"]}]}]}
**********************************
That blog explains the Value Type of the Filterstep, I am not sure those are supported as Data Type in Content Modifier.
User | Count |
---|---|
68 | |
10 | |
10 | |
10 | |
7 | |
7 | |
6 | |
5 | |
5 | |
5 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.