XQuery to get an attribute value with condition

1.5k Views Asked by At

I'm facing an issue with the parsing of a REST WebRequest' response

I'm using XQuery

For many years, I used a query which worked fine in my software (OneAutomation from Broadcom, formely Automic) I have updated the software to the next major version and now the query still work but the result is always empty I have tried a lot of different syntax but without success

Here is the query which worked with the old version of the software :

for $x in $input/BackgroundProcess/*/Process
return
if (($x/xs:string(@Created) > xs:string("&LastExecution#")) = true()) then
$x/xs:string(@Created)
else ()

The variable &LastExecution# contains a date (format for example : 2019-08-06 22:00:15 CEST) which is get by another GET Webrequest.

Here is a response example :

<BackgroundProcess>
  <Ended> 
    <Process Created="2019-08-06 22:00:15 CEST" Description="Export started for endpoint 'OIEP_ATTRIBUT' (2019-08-06 22:00:15)" Finished="2019-08-06 22:00:59 CEST" NumberOfErrors="0" NumberOfWarnings="0" Progress="0" StartedBy="STEPSYS" Started="2019-08-06 22:00:20 CEST" Status="succeeded" ID="BGP_1144216"/>
    <Process Created="2019-08-07 22:00:27 CEST" Description="Export started for endpoint 'OIEP_ATTRIBUT' (2019-08-07 22:00:27)" Finished="2019-08-07 22:01:15 CEST" NumberOfErrors="0" NumberOfWarnings="0" Progress="0" StartedBy="STEPSYS" Started="2019-08-07 22:00:32 CEST" Status="succeeded" ID="BGP_1152321"/>
  </Ended>
</BackgroundProcess>

The expected result is to have the most recent "Created" date, superior to the date passed in LastExecution#

Any help would be much appreciated

Edit : The following query works but I can't manage to get only the value of the attribute @Created

for $x in $input/BackgroundProcess/*/Process
return
if ($x [@Created > "&LastExcution#"]) then
$x
else()

It return the whole element :

<Process Created="2019-08-07 22:00:27 CEST" Description="Export started for endpoint 'OIEP_ATTRIBUT' (2019-08-07 22:00:27)" Finished="2019-08-07 22:01:15 CEST" NumberOfErrors="0" NumberOfWarnings="0" Progress="0" StartedBy="STEPSYS" Started="2019-08-07 22:00:32 CEST" Status="succeeded" ID="BGP_1152321"/> 
2

There are 2 best solutions below

0
On

I used latest BaseX 9.2.4 to test your XQuery. I ended up with the following:

XQuery

let $input := <BackgroundProcess>
  <Ended> 
    <Process Created="2019-08-06 22:00:15 CEST" Description="Export started for endpoint 'OIEP_ATTRIBUT' (2019-08-06 22:00:15)" Finished="2019-08-06 22:00:59 CEST" NumberOfErrors="0" NumberOfWarnings="0" Progress="0" StartedBy="STEPSYS" Started="2019-08-06 22:00:20 CEST" Status="succeeded" ID="BGP_1144216"/>
    <Process Created="2019-08-07 22:00:27 CEST" Description="Export started for endpoint 'OIEP_ATTRIBUT' (2019-08-07 22:00:27)" Finished="2019-08-07 22:01:15 CEST" NumberOfErrors="0" NumberOfWarnings="0" Progress="0" StartedBy="STEPSYS" Started="2019-08-07 22:00:32 CEST" Status="succeeded" ID="BGP_1152321"/>
  </Ended>
</BackgroundProcess>

let $LastExecution := '2019-08-06 22:00:15 CEST'

for $x in $input//Process
return 
if ($x [@Created > $LastExecution]) then
  data($x/@Created)
else()
5
On

That syntax in both samples where you say you access a variable seems to be a proprietary extension of your product, in standard XQuery a variable reference is just $var.

Anyway, it seems the part if ($x [@Created > "&LastExcution#"]) then $x could just be changed to if ($x [@Created > "&LastExcution#"]) then $x/@Created if your intent is to return the attribute node or if ($x [@Created > "&LastExcution#"]) then xs:string($x/@Created) if your intent is to return a string value of the attribute node.

In general, $input/BackgroundProcess/*/Process/@Created[. > "&LastExcution#"]/string() should do, there is no gain by using the for expression. But that is partly a question of personal preference of coding style and might be based on my inclination to use a plain XPath expression instead of a for expression.