Apu
Apu

Reputation: 167

Extracting the values of elements (XML) which is in an array and put it in the message property in Camel

As you can see the Availability Flag, BeamId is getting repeated. How do I traverse and set the property for Availability Flag1 and so on, so that I can later fetch it with velocity template?

Payload:<ns2:TransportFeasibilityResponse>
<ns2:Parameters>
<ns2:AvailabilityFlag>true</ns2:AvailabilityFlag>
<ns2:SatellitedID>H1B</ns2:SatellitedID>
<ns2:BeamID>675</ns2:BeamID>
<ns2:TransportName>Earth</ns2:TransportName>
</ns2:FeasibilityParameters>
<ns2:Parameters>
<ns2:AvailabilityFlag>true</ns2:AvailabilityFlag>
<ns2:SatellitedID>J34</ns2:SatellitedID>
<ns2:BeamID>111</ns2:BeamID>
<ns2:TransportName>Jupiter</ns2:TransportName>
</ns2:Parameters>
</ns2:TransportFeasibilityResponse>
</ns2:TransportFeasibilityResponseMsg> 


Code: (Its not complete)
public static HashMap<String,String> extractNameValueToProperties(String msgBody, selectedKeyList, namelist) throws Exception {

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setValidating(false);
        factory.setExpandEntityReferences(false);
        factory.setNamespaceAware(true);
        Document doc = null;
        try{
            DocumentBuilder builder = factory.newDocumentBuilder();
            doc = builder.parse(new InputSource(new StringReader(msgBody)));
        } catch(Exception ex) {
            Exception actException = new Exception( "Exception while extracting tagvalues", ex);
            throw actException;
        }

        HashMap<String,String> tagNameValueMap = new HashMap<String,String>();
        NodeList nodeList = doc.getElementsByTagName("*");
        // Trying to enter the TransportFeasibilityResponse element
        for (int i = 0; i < nodeList.getLength(); i++) {                        
            Node indNode = nodeList.item(i);
            if (indNode.indexOf(String name)>-1); 

//checking for Availability flag and similar namelist

            dataKey = indNode.getTextContent();
            message.setProperty(selectedKeyList[k], dataKey);   
            k++;
            j++;            
            else
            {
            continue;
            }
            }


    }

Here,
I am setting these values in my route:

<setProperty propertyName="namelist">                                       
<constant>AvailabilityFlag,SatellitedID,BeamID</constant>
</setProperty>

<setProperty propertyName="selectedKeyList">                                        
<constant>AvailabilityFlag1,SatellitedID1,BeamID1,AvailabilityFlag2,SatellitedID2,BeamID2 </constant>
</setProperty>
<bean beanType="com.gdg.dgdgdg.javacodename" method="extractNameValueToProperties"/>

Question: Please tell me how I can parse through the repeating elements and assign it to the property?

Thanks

Upvotes: 0

Views: 274

Answers (1)

Ricardo Zanini
Ricardo Zanini

Reputation: 1151

I'm not sure if I understand your question correctly, but I think you could use the Splitter pattern to split your xml per Parameters tag and process each other separately and aggregate it later.

Take for example this input:

<TransportFeasibilityResponse>
    <Parameters>
        <AvailabilityFlag>true</AvailabilityFlag>
        <SatellitedID>H1B</SatellitedID>
        <BeamID>675</BeamID>
        <TransportName>Earth</TransportName>
    </Parameters>
    <Parameters>
        <AvailabilityFlag>true</AvailabilityFlag>
        <SatellitedID>J34</SatellitedID>
        <BeamID>111</BeamID>
        <TransportName>Jupiter</TransportName>
    </Parameters>
</TransportFeasibilityResponse>

A route to process this input could be something like this:

from("direct:start")
    .split(xpath("/TransportFeasibilityResponse/Parameters"), new AggregationStrategy() {
        public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
            List<String> beamIDs = null;
            if (oldExchange == null) { // first
                beamIDs = new ArrayList<String>();
            } else {
                beamIDs = oldExchange.getIn().getBody(List.class);
            }

            beamIDs.add(newExchange.getIn().getBody(String.class));
            newExchange.getIn().setBody(beamIDs);
            return newExchange;
        }
    })
        .setBody(xpath("/Parameters/BeamID/text()"))
        .end()
    .log("The final body: ${body}");

First, we split the input per Parameters tag, and then extract the BeamID from it. After that, the AggregationStrategy aggregates each message into one, grouping by BeamID.

The final message should have the a body like this:

675,111

The data I put in the body just for an example, but you could set anywhere you want into the Exchange you are manipulating inside the AggregationStrategy implementation.

Upvotes: 1

Related Questions