How to store payload and append it to another payload later? - spring-integration

I am using Spring Integration in my project. I have the following payload.
<?xml version="1.0" encoding="UTF-8"?>
<PQ>
<PQContact>
<hostAddress>10.193.244.136</hostAddress>
</PQContact>
<workflowStatusComment>
<comment>I am here</comment>
</workflowStatusComment>
</PQ>
I want to extract the tag <workflowStatusComment> i.e workflowStatusComment <comment>I am here</comment></workflowStatusComment> and save it for future purpose. I don't want to use any java code to use the saved tag info in the future. I want to add the saved info to another payload at the end of the execution.I know about header enrichers, but I don't know how to use the saved header enriched values without using java. I have to only use Spring Integration components to manipulate the payload.
The second payload to which I am going to append the saved tag info is here:
<?xml version="1.0" encoding="UTF-8"?>
<PQ>
<PQContact>
<hostAddress>10.193.244.136</hostAddress>
<name>Ashok</name>
<userId>007</userId>
</PQContact>
</PQ>
After appending the saved tag info to the above payload, my final payload should look like the initial payload with some extra information. Something like below:
<?xml version="1.0" encoding="UTF-8"?>
<PQ>
<PQContact>
<hostAddress>10.193.244.136</hostAddress>
<name>Ashok</name>
<userId>007</userId>
</PQContact>
<workflowStatusComment>
<comment>I am here</comment>
</workflowStatusComment>
</PQ>
is there any way?

You can extract that info from the XML using <int-xml:xpath-transformer> or #xpath() SpEL-function.
But you have to share with us what is your "another payload" and how you would like to add this extracted.
Maybe it even better to have some solution with Java and than we consider here how to convert it into Spring Integration XML DSL or similar.
Please, revise your question to make it more clearer.
UPDATE
To insert one XML into another you have to fight a bit javax.xml API.
The code might be something like this:
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document target = builder.parse(new StringBufferInputStream(targetXML));
Element source = builder.parse(new StringBufferInputStream(sourceXML)).getDocumentElement();
target.appendChild(source);
UPDATE 2
But I don't want to use any java code.
Well, if your target XML can represent as a template string you can use standard replaceFirst() in the <transformer> with expression:
String targetXml = "";
<transformer expression="'<?xml version="1.0" encoding="UTF-8"?>
<PQ>
<PQContact>
<hostAddress>10.193.244.136</hostAddress>
<name>Ashok</name>
<userId>007</userId>
</PQContact>
$workflowStatusCommentToken$
</PQ>'.replaceFirst('\\$workflowStatusCommentToken\\$', headers.originalXml)"/>

Related

How to parse and edit XML in TypeScript without converting to JSON

I need to repair an XML file in TypeScript and I cannot find any info on it, since everyone who posts something like this has different needs. I'd like to be pointed in the right direction here.
I have an XML request as shown below. It is autogenerated by node-soap when given JSON. Using the WSDL, node-soap attempts to fill in the namespace prefixes for each property. The problem is, it gets them wrong a lot.
In this example below, q106 should be replaced with hep3.
<soap:Envelope q15="some-good-url" q106="some-good-url-1" q98-"some-good-url-2>
...
<q98:SalesOrderAuditInfo>
<q15:ConfirmedBy xsi:nil="true"></q15:ConfirmedBy>
<q15:ConfirmedDate>0001-01-01T00:00:00</q15:ConfirmedDate>
<q15:CreatedBy>
<q106:ID>103</q106:ID>
<q106:Value>System, System</q106:Value>
</q15:CreatedBy>
<q15:CreatedDate>2022-10-26T00:43:13.413</q15:CreatedDate>
<q15:SalesOrderType>Standard</q15:SalesOrderType>
</q98:SalesOrderAuditInfo>
I know which namespace prefixes are bad because I have a sample request that was supplied to me. It's just XML. It looks like this:
<soap:Envelope hep="some-good-url" hep1="some-good-url-1" hep2-"some-good-url-2 hep3="some-good-url-3">
...
<hep2:SalesOrderAuditInfo>
<hep:ConfirmedBy xsi:nil="true"></hep:ConfirmedBy>
<hep:ConfirmedBy:ConfirmedDate>0</hep:ConfirmedByConfirmedDate>
<hep:CreatedBy>
<hep3:ID>103</hep3:ID>
<hep3:Value>System, System</hep3:Value>
</hep:CreatedBy>
<hep:CreatedDate>0</hep:CreatedDate>
<hep:SalesOrderType>Standard</hep:SalesOrderType>
</hep2:SalesOrderAuditInfo>
Here is the part that really matters. The Sample Request is the entire possible request body. The supplied request (with incorrect namespaces) is a subset of the sample request. I need to loop through each of the elements in the supplied request, and check to make sure the URL of that element matches the URL of the respective element in the sample request.
So in this example, loop through each element of supplied request. Start with SalesOrderAuditInfo. It's namespace URL is some-good-url-2. If we check the Sample Request, we can see that SalesOrderAuditInfo also corresponds to some-good-url-2.
Continue until we hit the ID tag. This has a namespace set to some-good-url-1. If we check the Same ID (inside of CreatedBy, inside of SalesOrderAuditInfo), we can see the namespace should actually be set to some-good-url-3. So we replace q106 with hep3.
I also need to take all of the namespaces defined in the Sample Request Envelope and move them into the supplied request envelope so that this new hep3 will be defined.
At this point, I need to edit the namespace prefix. In this example, q106:ID would be replaced be the string hep3:ID. Same with all of the closing tags.
Which library can I use to accomplish this in XML? Is anyone familiar with node-soap screwing these namespaces up and know of any fix?
I am using node-soap v0.43

I get 'not implemented' response

Please see whether I'm right. A company claims that its cameras are Profile T compliant. So I visit this document to see what functions the cameras supports:
https://www.onvif.org/wp-content/uploads/2018/09/ONVIF_Profile_T_Specification_v1-0.pdf
In section 7.2.3 I see the function list for devices. I examine the first one, GetServices with the following command:
curl 192.168.11.92/onvif/device_service -d
'<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetServices xmlns="Battle of the Bulge, 75 years on" />
</soap12:Body>
</soap12:Envelope>'
The camera responds:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:c14n="Exclusive XML Canonicalization Version 1.0" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ds="XML-Signature Syntax and Processing" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:wsa="WS-Addressing 1.0 Namespace" xmlns:wsrfr="http://docs.oasis-open.org/wsrf/r-2" xmlns:wsrfrw="http://docs.oasis-open.org/wsrf/rw-2" xmlns:wsrfbf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:tavg="http://www.avigilon.com/onvif/ver10/avigilon-types" xmlns:tnsavg="http://www.avigilon.com/onvif/ver10/topics" xmlns:avg="http://www.avigilon.com/onvif/ver10/avigilon/wsdl" xmlns:avgb="http://www.avigilon.com/onvif/ver10/avigilon-base/wsdl" xmlns:d="Web Services Dynamic Discovery (WS-Discovery)">
<SOAP-ENV:Body>
<SOAP-ENV:Fault SOAP-ENV:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<SOAP-ENV:Code>
<SOAP-ENV:Value>
SOAP-ENV:Sender
</SOAP-ENV:Value>
</SOAP-ENV:Code>
<SOAP-ENV:Reason>
<SOAP-ENV:Text xml:lang="en">
Method 'GetServices' not implemented: method name or namespace not recognized
</SOAP-ENV:Text>
</SOAP-ENV:Reason>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
It says that the method is not implemented. Whatever I've examined until now got the same response. So I wonder maybe I've some mistakes in my requests.
Three points:
The namspace is wrong: xmlns="Battle of the Bulge, 75 years on". According to the Media 2 Service specs, it shall be http://www.onvif.org/ver20/media/wsdl.
This is not the way you are supposed to discover if a device supports Profile T. You should check if the scope onvif://www.onvif.org/Profile/T is returned by GetScopes or by discovering. A camera may implement Media Service 2 even if it is not Profile T compliant.
The best way to check if the claim of conformance to Profile T is correct, it to check the Declaration of Conformance being uploaded on the ONVIF website.
The correct way to specify the operation is
<wsdl:GetServices xmlns:wsdl="http://www.onvif.org/ver10/device/wsdl">
Reason: your main request,
<GetServices xmlns="Battle of the Bulge, 75 years on" />
is wrong for several reasons.
The most important is that you refer the operation by its local (unqualified) name. The correct name must be qualified, including a namespace. It is usually represented as {http://www.onvif.org/ver10/device/wsdl}GetService, but it must be used as wsdl:GetService
You can not use just any string as namespace; it must be the one that was used when the operation was defined (in this case, in devicemgmt.wsdl is defined as above)
Your definition of the namespace via xmlns is wrong, as it does not secify the namespace, only its value. The namespace used must be defined using the syntax xmlns:<uour namespace short>=<namespace as url>.
The namespace must be defined in the tag where it is used or one of its parents. It is most common to define all namespaces at the topmost level (root node/element)
and will return a list of services present, such as analytics, deviceio, event, etc. If the device supports Profile T, it will have Media2 service present, as below (not that is actually enabled, you need to use GetScopes for that or check the discovery message, as the other poster said)
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver20/media/wsdl</tds:Namespace>
<tds:XAddr>http://10.12.34.56/onvif/media_service</tds:XAddr>
<tds:Version>
<tt:Major>17</tt:Major>
<tt:Minor>12</tt:Minor>
</tds:Version>
</tds:Service>

NodeJS Amazon AWS Submit Feed Generic Error

I am trying to submit a product feed to AWS and I keep getting a generic error related to the XML I am sending
I have gone through all the .xsd files and come up what I believe to be correct xml but apparently not :(
The Error
{
"MessageID": "1",
"ResultCode": "Error",
"ResultMessageCode": "25",
"ResultDescription": "We are unable to process the XML feed because one or more items are invalid. Please re-submit the feed."
}
How I am creating the content
const getContent = (upc) => `<?xml version="1.0" encoding="iso-8859-1"?>
<AmazonEnvelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="amzn-envelope.xsd">
<Header>
<DocumentVersion>1.01</DocumentVersion>
<MerchantIdentifier>${process.env.MERCHANT_ID}</MerchantIdentifier>
</Header>
<MessageType>Product</MessageType>
<Message>
<MessageID>1</MessageID>
<OperationType>Update</OperationType>
<Product>
<SKU>${upc}</SKU>
</Product>
</Message>
</AmazonEnvelope>`
Turns out this just means a value in the xml is malformed. It helped a lot to search the xsd files for the specific variable I was trying to tie a value to and then it provides the restrictions on that value (i.e. AmazonOrderId has a regex validation associated with it that restricts the value to be in the structure of 123-1234567-1234567). After I manually ran through this process for each variable I was able to submit a feed finally but now I have to have an associated OrderAcknowledgement which I am working through.

Iterating over payload using special expression and construct dynamic input parameters for sql query

I am using Spring Integration in our project.My payload is as given below:
<?xml version="1.0" encoding="UTF-8"?>
<checkClaimSources>
<claimsCopy>
<ClmNum>07-111315-001-001</ClmNum>
<AltClaim />
</claimsCopy>
<claimsCopy>
<ClmNum>07-111315-001-002</ClmNum>
<AltClaim>test</AltClaim>
</claimsCopy>
</checkClaimSources>
I want to use int-jdbc:outbound-gateway to execute a select query where I have to provide all the <ClmNum> and <AltClaim> values as input parameters to the sql query. The number of <ClmNum> and <AltClaim> are dynamic here. Is there any way to iterate over all of those and pass them to the query?

Replace/Update a existing node value in groovy

Below is my sample xml.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header>
<MessageHeader xmlns:ns3="http://csi.cingular.com/CSI/Namespaces/Types/Public/CingularDataModel.xsd" xmlns:ns39="http://csi.cingular.com/CSI/Namespaces/Types/Public/MessageHeader.xsd">
<ns39:TrackingMessageHeader>
<ns3:infrastructureVersion>86</ns3:infrastructureVersion>
<ns3:version>222</ns3:version>
<ns3:messageId>146100035386400076</ns3:messageId>
<ns3:originatorId>PEEPS</ns3:originatorId>
<ns3:timeToLive>120000</ns3:timeToLive>
<ns3:dateTimeStamp>2016-04-18T20:16:19.387Z</ns3:dateTimeStamp>
</ns39:TrackingMessageHeader>
<ns39:SecurityMessageHeader>
<ns3:userName></ns3:userName>
<ns3:userPassword></ns3:userPassword>
</ns39:SecurityMessageHeader>
<ns39:SequenceMessageHeader>
<ns3:sequenceNumber>1</ns3:sequenceNumber>
<ns3:totalInSequence>1</ns3:totalInSequence>
</ns39:SequenceMessageHeader>
</MessageHeader> </SOAP-ENV:Header> <SOAP-ENV:Body>
<InquireEnterpriseOrderListRequest xmlns="http://csi.cingular.com/CSI/Namespaces/InquireEnterpriseOrderListRequest.xsd">
<SelectionCriteria>
<organizationId>214256542</organizationId>
</SelectionCriteria>
</InquireEnterpriseOrderListRequest> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
I want to replace "organizationId" this tag value with the value read from file and trigger it using testRunner.runTestStepByName("InquireEnterpriseOrderList") once the value is updated in the node.
Can any help in understanding how to update/replace node with new value and re-trigger the API to capture result for many inputs.
Here you what you need to do:
Read file extract the required value and store it at test case level custom property. Assuming that you are using groovy script test step to do this. So, add the below additional code:
//You assign value from your code, for now using dummy assignment
def requiredvalue = '123453'
//Store that value at test case level custom property, say ORGANIZATION_ID
context.testCase.setPropertyValue('ORGANIZATION_ID', requiredValue.toString())
Now, you do not need to update the request. Instead use, property expansion as below, so that SoapUI automatically takes care of the required value from proerties
<organizationId>${#TestCase#ORGANIZATION_ID}</organizationId>

Resources