2

This is my problem. Im receiving the following xml from a DS that has an event trigger to the ESB.

<messageCollection xmlns="http://services.core.solution.com/ds/queue">
   <message>
      <messageid>3083e5b9-f8fd-426f-a017-42439f47eefc</messageid>
      <messagetypeid>1</messagetypeid>
      <message>''</message>
      <processed>false</processed>
      <createddate>2014-12-30T14:38:11.782-04:00</createddate>
      <modifieddate>2014-12-30T14:38:11.782-04:00</modifieddate>
      <count>7</count>
   </message>
    <message>
      <messageid>2283e5b9-f8fd-426f-a017-42439f47eefc</messageid>
      <messagetypeid>2</messagetypeid>
      <message>''</message>
      <processed>false</processed>
      <createddate>2014-12-30T14:38:11.782-04:00</createddate>
      <modifieddate>2014-12-30T14:38:11.782-04:00</modifieddate>
      <count>7</count>
   </message>
</messageCollection>

and in a payload mediation Im implementing this:

<payloadFactory media-type="xml">
    <format>
        <p:updateLastPollingControl xmlns:p="http://services.core.solution.com/ds/queue">
            <xs:lastpolling xmlns:xs="http://services.core.solution.com/ds/queue">$1</xs:lastpolling>
        </p:updateLastPollingControl>
    </format>
    <args>
        <arg evaluator="xml" expression="//ns:message[last()]/ns:createddate" /> </args>
</payloadFactory>

Why it is always returning null value. If I harcoded the date everything works fine.

In a desperate move I also tried:

> //ns:message[last()]/ns:createddate/text() 
> /*/ns:message[last()]/ns:createddate   
> //ns:message[last()]/createddate
> /*/message[last()]/createddate

but nothing seems to work.

Any ideas? Thanks

Community
  • 1
  • 1
Ray
  • 483
  • 4
  • 17

3 Answers3

2

(Disclaimer: I am not familiar with WSO2, only with XML/XPath.)

It seems to me that your problem is due to the default namespace in your XML input:

<messageCollection xmlns="http://services.core.solution.com/ds/queue">

This default namespace not only applies to the messageCollection element, but all of its descendants, too, including the message element. Also, even if it is in a namespace, the element name of message remains "message", and is not "ns:message".

Further, I cannot see where you declare or register the namespace http://services.core.solution.com/ds/queue, i.e. associate it with the prefix ns:. If you don't, there is no connection between the prefix and the namespace.

To test this hypothesis, try

//*:message[last()]/*:createddate

and

//*[local-name() = 'message'][last()]/*[local-name() = 'createddate']

and let me know if those expressions return anything.


The above expressions do not really take into account namespaces, rather, they disregard them. The proper way to deal with namespaces is to declare them. According to this page, perhaps the correct way to register this namespace is

<args>
   <arg evaluator="xml" expression="//ns:message[last()]/ns:createddate" xmlns:ns="http://services.core.solution.com/ds/queue"/>
</args>
Mathias Müller
  • 22,203
  • 13
  • 58
  • 75
  • this one //*[local-name() = 'message'][last()]/*[local-name() = 'createddate'] was the magic one!! thanks – Ray Jan 01 '15 at 05:59
1

Just an idea, as this is only tested with different settings, but maybe you can check the following: I've just tested your XPath in the version

//*/message[last()]/createddate/text()

with the result 2014-12-30T14:38:11.782-04:00

Then I checked the result of

//*/message[last()]

which returned not just the last message, but instead

<message>''</message>
<message>
  <messageid>2283e5b9-f8fd-426f-a017-42439f47eefc</messageid>
  <messagetypeid>2</messagetypeid>
  <message>''</message>
  <processed>false</processed>
  <createddate>2014-12-30T14:38:11.782-04:00</createddate>
  <modifieddate>2014-12-30T14:38:11.782-04:00</modifieddate>
  <count>7</count>
</message>
<message>''</message>

which are in fact all last() message nodes - the two inner <message>''</message> nodes of both messages and the last/second message in the messagecontainer. To get only the second message, following XPath worked for me:

//*/message[not(parent::message)][last()]

which selects the last() message that has not parent message. So maybe you can try if you get the createddate with a namespace-adjusted version of

//*/message[not(parent::message)][last()]/createddate/text()

as it's possible that WSO2 XPath behaves different than the XPath tester I used which already retrieved the createddate with the expression mentioned first.

matthias_h
  • 11,356
  • 9
  • 22
  • 40
  • Thanks for the quick response. I tested all the xpaths listed here but all of them failed. I truly believe it is actually because of the namespace. If I used the xml as presented and load it in a tester with the namespace the result is null, if I eliminate the ns I got exactly what you got. So I tried to add, in wso2, the namespace in the form of ns: but every try was unsuccessful. Any other ideas? – Ray Dec 31 '14 at 02:50
  • @Ray Sorry to hear, just thought I better share the idea in case it would have been working like that for you in wso2. Shouldnt't take too long until someone (who can test in wso2) has the right idea.. Good luck! – matthias_h Dec 31 '14 at 03:01
1

You need to bind the ns prefix to the right namespace in the mediator configuration, like this:

<arg xmlns:ns="http://services.core.solution.com/ds/queue" ...
Andreas Veithen
  • 8,868
  • 3
  • 25
  • 28