Notas de la versión de motor de scripts 2 y posteriores

Los scripts que usan el motor de la versión 2 o posterior necesitan sintaxis adicional para aprovechar la funcionalidad de XPath 2. En general, se asumirá que cualquier variable declarada es una cadena. Esto significa que, si tiene previsto crear una sentencia matemática, es necesario declarar de forma explícita el tipo de datos de las variables como números enteros, números o fechas.

Nota: a menos que se indique lo contrario, todos los ejemplos de XPath en este tema corresponden al motor de la versión 1 (XPath 1). Las sentencias que funcionan con XPath 1 puede que no funcionen con XPath 2. Debe prestar especial atención sobre todo al ejecutar operaciones matemáticas. Puede consultar algunos ejemplos a continuación.

Aritmética de fecha y hora

Los tipos de datos de fecha y hora y de intervalo de XPath soportan operaciones ('+', '-', '*', etcétera) y funciones aritméticas que pueden usarse para realizar cálculos de tiempo de la misma forma que '1 + xs:integer(valor)' se utiliza para realizar cálculos numéricos.

Comparar duración:

if ("(xs:dateTime(fn:current-dateTime()) - xs:dateTime($updateDateTimeX))
   ge xs:dayTimeDuration(concat('PT', BO/hoursBetweenStatisticsUpdate, 'H'))")
   goto 60;
end-if;

Comparar una fecha con otra:

if ("xs:date(parm/endDate) < xs:date(parm/startDate)")
   terminate with error (11108, 11507 element='endDate');
end-if;

Comparar una fecha con la fecha de hoy:

if ("xs:date(parm/startDate) <= xs:date($CURRENT-DATE)")
   terminate with error (11108, 11507 element='endDate');
end-if;

Calcular el final de mes:

// covert to ISO
move "concat($year,'-',$mon2,'-01T00:00:00')" to $monthStart; 
 
// calculate
move "xs:dateTime($monthStart) + xs:yearMonthDuration('P1M') - xs:dayTimeDuration('P0DT1S')" 
  to $monthEnd;
 
// convert from ISO to OUAF
move "concat($year,'-',$mon2,'-',substring(string($monthEnd),9,2),'-23.59.59')" to $endDateTime;
Nota: los formatos de fecha/hora/intervalo de XPath utilizan el estándar ISO, que debe convertirse a/desde los formatos soportados en el marco.

Comparaciones de fecha y hora en formato de cadena

Todos los formatos de cadena similares al formato ISO de fecha y hora mantiene la secuencia AAAA MM DD HH MM SS, que se rellena con ceros. Con independencia de los separadores, este formato seguirá siendo adecuado para las operaciones de comparación. En concreto, los valores de fecha y hora del formato de marco “AAAA-MM-DD.HH.MM.SS” se puede usar con “=”, “!=”, y también con los operadores “>”, “>=”, “<”, “<=”.

// retrieve framework date/time value
invokeBS 'CM-MAXMSRMT' using "CM-MAXMSRMT";
move "string(cm-MAXMSRMT/results[1]/measurementDateTime)" to $lastMsmtDT;
 
// construct another date/time
move "concat($year,'-01-01-00.00.00')" to $startDateTime;
 
// compare using string operators
if ("$lastMsmtDT >= $startDateTime")
    move "substring($lastMsmtDT,1,4)" to $latestMsrmtYear;

Conversiones de fecha y hora entre el marco e ISO

La conversión de fecha y hora del formato de marco a ISO solo es necesaria para la aritmética de fecha y hora. Las comparaciones se pueden hacer de forma directa con el formato de marco. La única diferencia entre el formato de marco y los formatos de fecha/hora ISO se encuentra en los separadores:

Marco: “AAAA-MM-DD.HH.MM.SS”

ISO: “AAAA-MM-DDTHH:MM:SS”

Ejemplo de conversión del formato de marco a ISO:

move "concat(substring($ouafDT, 1, 10), 'T', translate(substring($ouafDT, 12),'.',':'))" to $isoDT;

Ejemplo de conversión de ISO al formato de marco:

move "concat(substring($isoDT, 1, 10), '.', translate(substring($isoDT, 12),':','.'))" to $ouafDT;

Redondear importes monetarios con una escala de divisas dinámica

Debido a que diversas divisas soportan un número distinto de decimales, el marco proporciona una API para redondear importes monetarios según una divisa determinada.

move "parm/amount" to $qnty;
move "currency/decimals" to $decimals;
move "fn:round(xs:decimal($qnty) * math:exp10(xs:double($decimals))) 
  div math:exp10(xs:double($decimals))" to "parm/roundedAmount";

Bucles en secuencias

En XPath 2 es posible organizar un bucle para una secuencia de números enteros, no solo una lista de nodos.

En este ejemplo se muestra un bucle en un rango de meses. Esta es una estructura de formación de secuencia en XPath. La lista de nodos de XPath, con la que está familiarizado, es solo otro tipo de secuencia.

for ($month in "1 to 12")

Este ejemplo muestra un bucle en un rango de años determinado en orden descendente:

for ($year in "fn:reverse(parm/startYear to parm/endYear)")
     move "concat($year,'-01-01-00.00.00')" to $startDateTime;
     move "concat($year,'-12-31-23.59.59')" to $endDateTime;
     ...   

Este ejemplo muestra un bucle en una lista de nodos en la que se usa 'index' para que se pueda acceder a otras listas de nodos:

for ($idx in "1 to count(parm/touData/touList)")
     move "parm/touData/touList[$idx]" to $tou;   // access any list with this index   

La sintaxis anterior se puede usar como una alternativa elegante para el mantenimiento de índices de forma separada, en lugar del ejemplo siguiente:

move “0” to $idx;
for ($item in "parm/touData/touList")
     move “1 + xs:integer($idx)” to $idx;

Relleno de cadenas y formato decimal

Se utiliza para formatos de entrada específicos o formatos de salida. Es aplicable a ceros, espacios y otros tipos de relleno.

En este ejemplo se muestra la inclusión de prefijos a los componentes de fecha/hora (por ejemplo, para que el resultado sea “2010-01-02” en lugar de “2010-1-2”).

move "substring(concat('0',string($month)), string-length(string($month)), 2)" to $mon2; 

En este ejemplo se muestra la inclusión de sufijos para añadir una alineación decimal rellenada con ceros (por ejemplo, para que los resultados sean “12.30” y “4.00” en lugar de “12.3” y “4”). En el ejemplo se realizan 3 tareas: redondear a 2 decimales, insertar un punto si es necesario y rellenar con ceros.

// round and zero-pad to 2 decimals
move "$item/amount" to $qty;
move "fn:round(xs:double($qty) * 100) div 100" to $qty;
move "string($qty)" to $qty;
move "concat(substring-before(concat($qty,'.'),'.'),'.',substring(concat(substring-after($qty,'.'),'00'),1,2))" to $qty;

Operación ternaria

Realiza una elección entre valores basados en una condición para que pueda usarse en una sola expresión en lugar de en un bloque if/else. La sintaxis en C/C++ sería ‘condición ? valor1 : valor2’ y en BASIC sería ‘IFF(condición, valor1, valor2)’. En XPath la sintaxis es: "if (condición) then valor1 else valor2". Tenga en cuenta que este no es el bloque de sentencias "if" de scripts de nivel superior.

En XPath esto es una expresión que se puede combinar con otras expresiones. En la generación de scripts se puede usar como:

move "if (string(D1-UnitOfMeasure/measuresPeakQuantity) = 'D1MP') then 'D1MX' else 'D1SM' " to $func;

Proceso de pipeline

En la generación de scripts no resulta fácil crear una porción de código reutilizable que sea simple, ya que no hay funciones locales, y una llamada a script independiente supone un exceso de codificación y requiere parámetros de empaquetado/desempaquetado. Para evitar tener que copiar y pegar el mismo bloque de código en etapas de script similares, considere usar el "pipelining", que divide el proceso general en pasos de nivel superior independientes, algunos de los cuales pueden compartirse entre rutas alternas. Esto es habitual en la preparación de parámetros y en los formatos de salida. Un resultado intermedio entre etapas puede almacenarse en una subestructura de “parámetros”.

En lugar de este código:

if ("type = A")
   prepare params ...
   call services for A ...
   format output ...
end-if;
if ("type = B")
   prepare params ...
   call services for B ...
   format output ...
end-if;

Considere esta alternativa:

prepare params ...

if ("type = A")
   call services for A ...
end-if;
if ("type = B")
   call services for B ...
end-if;

format output ...

Funciones de XPath 2

Las versiones 2 y posteriores del motor de scripts soportan las funciones y operadores de XQuery 1.0 y el propio estándar XQuery 1.0 con algunas limitaciones menores. A continuación se muestran las URL de ambas especificaciones. En el primer enlace se encuentran las funciones y operadores disponibles para usar desde XQuery.

  • http://www.w3.org/TR/xpath-functions/

  • http://www.w3.org/TR/xquery/

Mediante la siguiente función solo puede acceder a los sistemas de ficheros locales. Para otros protocolos (por ejemplo, http) se devolverá una secuencia vacía:

  • fn:doc

  • fn:collection