Search code examples
xpathcontainsazure-logic-apps

xpath xml take first value based on sibling value


I have a Logic app that i used to get values in a XML show below. I need to fetch the first ws:Transaction_Entry_Moment that contains "ID Change" text and ws:Is_Rescind_Or_Rescinded value has to be "false"

<ws:Transaction_Log_Data>      
  <ws:Transaction_Log_Entry>
    <ws:Transaction_Log_Description>Change Contacts for: XYZ</ws:Transaction_Log_Description>
    <ws:Transaction_Entry_Moment>2020-11-05T20:25:58.439-08:00</ws:Transaction_Entry_Moment>
    <ws:Is_Rescind_Or_Rescinded>false</ws:Is_Rescind_Or_Rescinded>
  </ws:Transaction_Log_Entry>
  <ws:Transaction_Log_Entry>
    <ws:Transaction_Log_Description>ID Change: XYZ</ws:Transaction_Log_Description>
    <ws:Transaction_Entry_Moment>2020-11-05T20:25:58.439-08:00</ws:Transaction_Entry_Moment>
    <ws:Is_Rescind_Or_Rescinded>false</ws:Is_Rescind_Or_Rescinded>
  </ws:Transaction_Log_Entry>
  <ws:Transaction_Log_Entry>
    <ws:Transaction_Log_Description>ID Change: XYZ</ws:Transaction_Log_Description>
    <ws:Transaction_Entry_Moment>2020-11-05T20:25:58.439-08:00</ws:Transaction_Entry_Moment>
    <ws:Is_Rescind_Or_Rescinded>false</ws:Is_Rescind_Or_Rescinded>
  </ws:Transaction_Log_Entry>      
</ws:Transaction_Log_Data>

I used the following xpath in my logic app, it returns empty

"DATE": "@xpath(xml(triggerBody()), 'string(/*[local-name()=\"Transaction_Log_Data\"]/*[local-name()=\"Transaction_Log_Entry\"]/*[local-name()=\"Is_Rescind_Or_Rescinded\" and .= \"false\" and contains(@*[local-name()=\"Transaction_Log_Description\"], \"ID Change\")][position() = 1]/../*[local-name()=\"Transaction_Entry_Moment\"])')"

if i remove the contains in the xpath as shown below, it fetches me the first ws:Is_Rescind_Or_Rescinded where it's "false"

"DATE": "@xpath(xml(triggerBody()), 'string(/*[local-name()=\"Transaction_Log_Data\"]/*[local-name()=\"Transaction_Log_Entry\"]/*[local-name()=\"Is_Rescind_Or_Rescinded\" and .= \"false\"][position() = 1]/../*[local-name()=\"Transaction_Entry_Moment\"])')"

Is there something wrong with the contains i'm using? what is right way to acheieve this?


Solution

    1. @ is used to point on attribute not an element
    2. The predicate is applied to wrong element

    Try this

    'string(/*[local-name()=\"Transaction_Log_Data\"]/
       *[local-name()=\"Transaction_Log_Entry\" and contains(*[local-name()=\"Transaction_Log_Description\"], \"ID Change\")]/
          *[local-name()=\"Is_Rescind_Or_Rescinded\" and .= \"false\" ][position() = 1]/../
              *[local-name()=\"Transaction_Entry_Moment\"])'