MULE: xpath expression not extracting values from payload

1.8k views Asked by At

I've got a simple flow, it takes an XML messages, splits it into sub elements and now I am trying to get a value, but getting unexpected results.

My XML looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<ns0:RewardOfferDetail xmlns:ns0="http://example.com/schemas/v1_0/RewardOffer">
  <ns0:Offer>
    <ns0:OperationCode>U</ns0:OperationCode>
  </ns0:Offer>
  <ns0:Offer>
    <ns0:OperationCode>A</ns0:OperationCode>
  </ns0:Offer>
</ns0:RewardOfferDetail>

I need to extract the <OpeartionCode> from each <Offer>

The split works fine, and when I log out the payload after the split, it is a <Offer> just fine. but then I try to extract the value of <OperationCode> using this:

#[xpath('/rewardsns:Offer/rewardns:OperationCode')]

I get nothing, just a null value, then I try using a broader xpath expression:

#[xpath('//rewardns:OperationCode')]

And the result is two nodes, which leads me to believe that the xpath function is not looking at the right spot. but I've even trying telling it where to look and still no luck.

#[xpath('//rewardns:OperationCode', message.payload)]
#[xpath('//rewardns:OperationCode', payload)]

still yields two nodes.

Any Suggestions?

Flow:

    <flow name="receiveMessageFlow">
    <jms:inbound-endpoint
        queue="#{loyaltySettings.getString('loyalty.queue.receive')}"
        connector-ref="jmsConnector" doc:name="Loyalty Queue" />

    <message-filter doc:name="XSD Validation" onUnaccepted="invalidXmlMessage">
        <filter ref="schemaValidation" />
    </message-filter>

    <splitter expression="#[xpath('/rewardns:RewardOfferDetail/rewardns:Offer')]" doc:name="Split Message" />

    <set-variable variableName="action" value="#[xpath('//rewardns:OperationCode')]" doc:name="Save Action Code"/>

    <logger message="Action is: '#[flowVars.action]'" level="WARN" doc:name="Log Action Code"/>

Output:

13:53:39,653 DEBUG [org.mule.transport.jms.MultiConsumerJmsMessageReceiver] (TIBCO EMS Session Dispatcher (741)) Message received it is of type: TibjmsTextMessage
13:53:39,653 DEBUG [org.mule.transport.jms.MultiConsumerJmsMessageReceiver] (TIBCO EMS Session Dispatcher (741)) Message received on Queue[M.ESS.ITM.LOYALTY.STARS.ItemMaint] (com.tibco.tibjms.TibjmsQueue)
13:53:39,653 DEBUG [org.mule.transport.jms.MultiConsumerJmsMessageReceiver] (TIBCO EMS Session Dispatcher (741)) Message CorrelationId is: 
13:53:39,653 DEBUG [org.mule.transport.jms.MultiConsumerJmsMessageReceiver] (TIBCO EMS Session Dispatcher (741)) Jms Message Id is: ID:EMS-SERVER.A305502CE7A4:995
13:53:39,653 DEBUG [org.mule.transport.jms.transformers.JMSMessageToObject] (TIBCO EMS Session Dispatcher (741)) Applying transformer JMSMessageToObject#218219976 (org.mule.transport.jms.transformers.JMSMessageToObject)
13:53:39,653 DEBUG [org.mule.transport.jms.transformers.JMSMessageToObject] (TIBCO EMS Session Dispatcher (741)) Object before transform: 
org.mule.DefaultMuleMessage
{
  id=998d2f50-13a0-11e5-b0f9-ac87a31af20c
  payload=com.tibco.tibjms.TibjmsTextMessage
  correlationId=
  correlationGroup=-1
  correlationSeq=-1
  encoding=UTF-8
  exceptionPayload=<not set>

Message properties:
  INVOCATION scoped properties:
  INBOUND scoped properties:
    JMSCorrelationID=
    JMSDeliveryMode=1
    JMSDestination=Queue[M.ESS.ITM.LOYALTY.STARS.ItemMaint]
    JMSExpiration=0
    JMSMessageID=ID:EMS-SERVER.A305502CE7A4:995
    JMSPriority=4
    JMSRedelivered=false
    JMSTimestamp=1426256459016
    JMSType=
    MULE_CORRELATION_ID=
    MULE_MESSAGE_ID=ID:EMS-SERVER.A305502CE7A4:995
  OUTBOUND scoped properties:
    MULE_ENCODING=UTF-8
  SESSION scoped properties:
}
13:53:39,654 DEBUG [org.mule.transport.jms.transformers.JMSMessageToObject] (TIBCO EMS Session Dispatcher (741)) Source object is TibjmsTextMessage
13:53:39,654 DEBUG [org.mule.transport.jms.transformers.JMSMessageToObject] (TIBCO EMS Session Dispatcher (741)) Message type received is: TibjmsTextMessage
13:53:39,654 DEBUG [org.mule.transport.jms.transformers.JMSMessageToObject] (TIBCO EMS Session Dispatcher (741)) Resulting object is String
13:53:39,654 DEBUG [org.mule.transport.jms.transformers.JMSMessageToObject] (TIBCO EMS Session Dispatcher (741)) Object after transform: <?xml version="1.0" encoding="UTF-8" ?>
<ns0:RewardOfferDetail xmlns:ns0="http://example.com/schemas/v1_0/RewardOffer">
  <ns0:Offer>
    <ns0:OperationCode>U</ns0:OperationCode>
  </ns0:Offer>
  <ns0:Offer>
    <ns0:OperationCode>A</ns0:OperationCode>
  </ns0:Offer>
</ns0:RewardOfferDetail>
13:53:39,654 DEBUG [org.mule.transport.jms.transformers.JMSMessageToObject] (TIBCO EMS Session Dispatcher (741)) The transformed object is of expected type. Type is: String
13:53:39,669 DEBUG [org.mule.expression.DefaultExpressionManager] ([loyalty-nebula].receiveMessageFlow.stage1.02) Result of expression: xpath-branch:/rewardns:RewardOfferDetail/rewardns:Offer is: [[ns0:Offer: null], [ns0:Offer: null]]
13:53:39,669 DEBUG [org.mule.processor.chain.DefaultMessageProcessorChain] ([loyalty-nebula].receiveMessageFlow.stage1.02) Invoking DefaultMessageProcessorChain '(inner iterating chain) of 'receiveMessageFlow' processor chain' 
[ 
  AddFlowVariableTransformer{this=589f1380, name='AddFlowVariableTransformer', ignoreBadInput=false, returnClass=SimpleDataType{type=java.lang.Object, mimeType='*/*'}, sourceTypes=[SimpleDataType{type=java.lang.Object, mimeType='*/*'}]}, 
  org.mule.api.processor.LoggerMessageProcessor@be3c4ce, 
  org.mule.routing.requestreply.AsyncReplyToPropertyRequestReplyReplier
] with event MuleEvent: 0-998d2f53-13a0-11e5-b0f9-ac87a31af20c, stop processing=false, jms://M.ESS.ITM.LOYALTY.STARS.ItemMaint
13:53:39,669 DEBUG [org.mule.transformer.simple.AddFlowVariableTransformer] ([loyalty-nebula].receiveMessageFlow.stage1.02) Applying transformer AddFlowVariableTransformer (org.mule.transformer.simple.AddFlowVariableTransformer)
13:53:39,670 DEBUG [org.mule.transformer.simple.AddFlowVariableTransformer] ([loyalty-nebula].receiveMessageFlow.stage1.02) Object before transform: 
org.mule.DefaultMuleMessage
{
  id=998fa050-13a0-11e5-b0f9-ac87a31af20c
  payload=org.apache.xerces.dom.ElementNSImpl
  correlationId=<not set>
  correlationGroup=2
  correlationSeq=1
  encoding=UTF-8
  exceptionPayload=<not set>

Message properties:
  INVOCATION scoped properties:
  INBOUND scoped properties:
  OUTBOUND scoped properties:
    MULE_CORRELATION_GROUP_SIZE=2
    MULE_CORRELATION_SEQUENCE=1
    MULE_ENCODING=UTF-8
  SESSION scoped properties:
}
13:53:39,670 DEBUG [org.mule.expression.DefaultExpressionManager] ([loyalty-nebula].receiveMessageFlow.stage1.02) Result of expression: xpath-branch://rewardns:OperationCode is: [[ns0:OperationCode: null], [ns0:OperationCode: null]]
13:53:39,670 DEBUG [org.mule.transformer.simple.AddFlowVariableTransformer] ([loyalty-nebula].receiveMessageFlow.stage1.02) Object after transform: 
org.mule.DefaultMuleMessage
{
  id=998fa050-13a0-11e5-b0f9-ac87a31af20c
  payload=org.apache.xerces.dom.ElementNSImpl
  correlationId=<not set>
  correlationGroup=2
  correlationSeq=1
  encoding=UTF-8
  exceptionPayload=<not set>

Message properties:
  INVOCATION scoped properties:
    action=[[ns0:OperationCode: null], [ns0:OperationCode: null]]
  INBOUND scoped properties:
  OUTBOUND scoped properties:
    MULE_CORRELATION_GROUP_SIZE=2
    MULE_CORRELATION_SEQUENCE=1
    MULE_ENCODING=UTF-8
  SESSION scoped properties:
}
13:53:39,671 DEBUG [org.mule.transformer.simple.AddFlowVariableTransformer] ([loyalty-nebula].receiveMessageFlow.stage1.02) The transformed object is of expected type. Type is: DefaultMuleMessage
13:53:39,672 WARN  [org.mule.api.processor.LoggerMessageProcessor] ([loyalty-nebula].receiveMessageFlow.stage1.02) Action is: '[[ns0:OperationCode: null], [ns0:OperationCode: null]]'
2

There are 2 answers

0
JD Frias On BEST ANSWER

This seems to work

    xpath('./rewardns:OperationCode')

From what @David was explaining it seems that xpath can still access elements throughout the entire document. A way to get around this was to use a ./ in the expression to anchor the function to use the current node as a starting point.

So the final component looks like this:

    <set-variable variableName="action" value="#[xpath('./rewardns:OperationCode').getFirstChild().getNodeValue()]" doc:name="Save Action Code"/>
4
David Dossot On

The splitter produces messages with Offer DOM elements as their payloads.

If you use an xpath expression starting with // you are navigating back to the root element, which is still navigable from the Offer element (because splitting doesn't detach the DOM nodes).

So you need to base your xpath on the current Offer element with:

#[xpath('rewardns:OperationCode').nodeValue]

Note that you could also use MEL instead of xpath to read the content of the Offer DOM element:

<set-variable variableName="action"
    value="#[message.payload.getElementsByTagNameNS('http://example.com/schemas/v1_0/RewardOffer','OperationCode').nodeValue]"
    doc:name="Save Action Code"/>