0

I have a complication of the "usual" question of how to return a string value based on XPATH condition.

I've successfully used the following solutions before: Return a string value based on XPATH condition and Nested conditional if else statements in xpath

But now my XML is:

<Events xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <EventDetails>
    <AccountingDate>2017-01-01</AccountingDate>
    <PaymentDate>2017-01-31</PaymentDate>
  </EventDetails>
  <EventDetails>
    <AccountingDate>2017-01-01</AccountingDate>
    <PaymentDate xsi:nil="true"/>
  </EventDetails>
</Events>

and I need to extract the PaymentDate if it has a value but otherwise substitute the AccountingDate i.e. 2017-01-31 for the first Event but 2017-01-01 for the second.

The problem is that the parser I'm forced to use is XPath 1.0 and does not recognize the nilled function and boolean(PaymentDate) is true if PaymentDate is nil.

I hope someone has a bright idea because I'm totally stumped.

2 Answers2

1

Finally solved it after about 4 hours...

concat(substring(PaymentDate,   1 div    (boolean(PaymentDate) and PaymentDate!='')),
       substring(AccountingDate,1 div not(boolean(PaymentDate) and PaymentDate!='')))

(It also caters for the possibility that PaymentDate doesn't exist at all although in my case it always does.)

Now I just need to make it work with three possible dates!

0

You can also try this filtering

EventDetails[PaymentDate != '']/PaymentDate | EventDetails[PaymentDate = '']/AccountingDate

or on the actual level

PaymentDate[. != ''] | AccountingDate[../PaymentDate = '']

or if it is important to work when PaymentDate missing and xml data order is fixed

PaymentDate[. != ''] | AccountingDate[not(following-sibling::PaymentDate) or following-sibling::PaymentDate = '']
VargaJoe
  • 175
  • 5
  • 10
  • Thanks. I like the idea of filtering the selection of PaymentDate by its own existence; that hadn't occurred to me. – user9267428 Jan 26 '18 at 01:07
  • Yeah, it's works because it's actually string emptyness test, `*[. != '']` is same as `*[string(.) != '']` or `*[./text() != '']`and filters elements expected with a string value. Element's existence filtering would be `*[PaymentDate]` or `*[name() = 'PaymentDate']`which give all elements matching the given name regardless of it's value. – VargaJoe Jan 26 '18 at 05:48