2 votes

L'invocation d'une fonction de mise à jour XQuery entraîne l'erreur suivante Si une sous-expression est en cours de mise à jour, alors toutes doivent être en cours de mise à jour.

Mon document XML contient un enregistrement du mouvement d'un objet. Le document XML consiste en une série d'observations. Chaque observation contient la position lat/long de l'objet, la position lat/long du capteur d'observation et un horodatage.

<Track-History>
    <Track-ID>XYZ</Track-ID>
    <Observation>
        <Target-Latitude>10.3</Target-Latitude>
        <Target-Longitude>20.8</Target-Longitude>
        <Observer-Latitude>40.0</Observer-Latitude>
        <Observer-Longitude>50.0</Observer-Longitude>
        <DateTime>20230202T071700.00</DateTime>
    </Observation>
    <Observation>
        <Target-Latitude>15.1</Target-Latitude>
        <Target-Longitude>25.2</Target-Longitude>
        <Observer-Latitude>40.0</Observer-Latitude>
        <Observer-Longitude>50.0</Observer-Longitude>
        <DateTime>20230202T071800.00</DateTime>
    </Observation>
</Track-History>

Je veux brouiller les emplacements de l'objet en arrondissant les valeurs décimales de latitude et de longitude. J'ai donc créé cette fonction de mise à jour :

declare updating function f:fuzzPoint($lat as element(), $long as element())
{
    replace node $lat with 
        element {name($lat)} {round(number(data($lat)))},
    replace node $long with 
        element {name($long)} {round(number(data($long)))}
};

Lorsque j'invoque cette fonction :

{f:fuzzPoint($obs/Target-Latitude, $obs/Target-Longitude)}

J'obtiens ce message d'erreur :

If any subexpression is updating, then all must be updating

Oxygen XML affiche une ligne rouge sous les arguments de la fonction, ce qui signifie que les arguments doivent être mis à jour. Oui ? Si oui, comment faire pour que les arguments soient mis à jour ?

Vous trouverez ci-dessous mon programme complet de mise à jour XQuery.

declare namespace f = "function";

declare variable $Track-History := doc('Track-History.xml');
declare variable $track-history-points := (for $i in $Track-History//Observation return [$i/Target-Latitude, $i/Target-Longitude]);
declare variable $AOR := (); (: should be a sequence of points, fake it for now :)

declare function f:isInside($points, $polygon) as xs:boolean
{
    true()
};

declare updating function f:fuzzPoint($lat as element(), $long as element())
{
    replace node $lat with 
        element {name($lat)} {round(number(data($lat)))},
    replace node $long with 
        element {name($long)} {round(number(data($long)))}
};

if (f:isInside($track-history-points, $AOR)) then
    for $obs in $Track-History//Observation return
      replace node $obs with
      <Observation>
            {f:fuzzPoint($obs/Target-Latitude, $obs/Target-Longitude)}
            {$obs/Observer-Latitude}
            {$obs/Observer-Longitude}
            {$obs/DateTime}
       </Observation>
else
   replace node $Track-History/* with
      <Track-History/>

3voto

Christian Grün Points 2150

A l'intérieur d'une expression de mise à jour - replace node $obs with ... - il n'est pas autorisé à effectuer d'autres mises à jour. Le code fonctionne si vous modifiez f:fuzzPoint de telle sorte qu'il renvoie les nouveaux nœuds de l'élément :

declare function f:fuzzPoint($lat as element(), $long as element()) {
  element { name($lat) } { round(number(data($lat))) },
  element { name($long) } { round(number(data($long))) }
};

En updating dans la déclaration de la fonction a du sens si vous déplacez l'opération de mise à jour à l'intérieur du corps de la fonction :

declare updating function f:replace($obs as element()) {
  let $lat := $obs/Target-Latitude
  let $long := $obs/Target-Longitude
  return replace node $obs with <Observation>{
    element { name($lat) } { round(number(data($lat))) },
    element { name($long) } { round(number(data($long))) },
    $obs/Observer-Latitude,
    $obs/Observer-Longitude,
    $obs/DateTime
  }</Observation>
};

if (f:isInside($track-history-points, $AOR)) then
  for $obs in $Track-History//Observation return f:replace($obs)
else
   replace node $Track-History/* with
      <Track-History/>

1voto

Martin Honnen Points 46896

Je me demande si

declare namespace f = "function";

declare variable $Track-History := doc('Track-History.xml');
declare variable $track-history-points := (for $i in $Track-History//Observation return [$i/Target-Latitude, $i/Target-Longitude]);
declare variable $AOR := (); (: should be a sequence of points, fake it for now :)

declare function f:isInside($points, $polygon) as xs:boolean
{
    true()
};

declare function f:fuzzValue($v as xs:double) as xs:double
{
  round($v)
};

if (f:isInside($track-history-points, $AOR)) then
    for $lv in $Track-History//Observation/(Target-Latitude, Target-Longitude) 
    return
      replace value of node $lv  
      with f:fuzzValue($lv)

else
   replace node $Track-History/* with
      <Track-History/>

c'est tout ce que vous voulez faire ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X