Utilización de funciones externas con XQuery

Cuando utilice una expresión XQuery que utilice funciones externas, declare las firmas de función en el prólogo de XQuery como funciones externas o utilizando una instancia XStaticContext. Proporciona (o enlace) una implementación Java para cada función utilizando una instancia XDynamicContext.

Procedimiento

  1. Cuando prepare una expresión XQuery que utilice funciones externas, declare las firmas de función en el prólogo de XQuery o utilizando una instancia XStaticContext.

    Las funciones declaradas en XStaticContext sólo son visibles para el módulo principal. Para que una función externa sea visible para un módulo de biblioteca, debe declararse en el prólogo de ese módulo de biblioteca.

    La interfaz XStaticContext tiene dos métodos declareFunction, cada uno de los cuales tiene tres parámetros: uno para el nombre, uno para el tipo de retorno de la función y una matriz para los tipos de argumentos. El nombre siempre se proporciona como objeto QName pero los tipos pueden ser Qnames o XSequenceTypes. El nombre de función, el tipo de retorno y los tipos de argumento deben identificar de forma exclusiva la función.

    Tabla 1. Métodos declareFunction de XStaticContext.

    En esta tabla se explica cuándo se utiliza cada forma del método declareFunction.

    Firma de método Finalidad
    declareFunction(QName name, QName type, QName[] argTypes) Se utiliza cuando el valor de retorno y los argumentos de la función sean valores atómicos únicos

    El tipo QNames debe hacer referencia a los tipos incorporados o tipos globales declarados en un esquema que se ha registrado en la instancia XFactory que se utiliza para crear la instancia XStaticContext. Si un QName hace referencia a un tipo no atómico, el procesador lo tratará como el tipo element(*, ns:type), donde ns:type es el QName indicado. La interfaz XTypeConstants tiene disponibles constantes adecuadas que proporcionan un objeto QName para cada tipo incorporado.

    declareFunction(QName name, XSequenceType type, XSequenceType[] argTypes) Se utiliza cuando cualquiera de los argumentos o el valor de retorno de la función es un nodo o una secuencia de valores atómicos o nodos
    La siguiente expresión XQuery utiliza tres funciones, dos de las cuales se declaran en el prólogo.
    declare namespace xs = "http://www.w3.org/2001/XMLSchema";
    declare namespace trig = "http://www.example.org/trigonometry";
    declare function trig:arctan($ratio as xs:double) as xs:double external;
    declare function trig:sin($angle as xs:double) as xs:double external;
    
    <ramps>
    {
        for $ramp in ramps/ramp
        let $angleRadians := trig:arctan($ramp/height div $ramp/base)
        let $angle := trig:toDegrees($angleRadians)
        let $length := $ramp/height div trig:sin($angleRadians)
        return
            element ramp
            {
                $ramp/height,
                $ramp/base,
                element angle { $angle },
                element length { $length }
            }
    }
    </ramps>
    Si suponemos que la consulta especificada está disponible utilizando el objeto de fuente xquerySource, el código siguiente prepara la consulta. La función que no se declaró en la propia consulta, trig:toDegrees, se declara en la instancia XStaticContext.
    // Create the factory
    XFactory factory = XFactory.newInstance();
    
    // Create a new static context
    XStaticContext staticContext = factory.newStaticContext();
    
    // Declare a namespace for the functions
    staticContext.declareNamespace("trig", "http://www.example.org/trigonometry");
    
    // Create a QName for the trig:toDegrees function
    QName toDegreesQName = new QName("http://www.example.org/trigonometry", "toDegrees");
    
    // Declare the function on the static context
    staticContext.declareFunction(toDegreesQName, XTypeConstants.DOUBLE_QNAME, new QName[]{XTypeConstants.DOUBLE_QNAME});
    
    // Create an XQuery executable for the query
    XQueryExecutable executable = factory.prepareXQuery(xquerySource, staticContext);
  2. Para ejecutar una expresión XQuery que utiliza funciones externas, proporcione (o enlace) los métodos Java que implementan las funciones utilizando una instancia XDynamicContext.

    Los enlaces para funciones externas estarán disponibles para el módulo principal y para los módulos de biblioteca que tengan una declaración de función externa en su prólogo para esa función.

    Utilice el reflejo Java para obtener un objeto java.lang.reflect.Method para la función. Si el método es un método de instancia, será necesario un objeto de instancia cuando se enlace esta función.

    Se llega a un error si no se proporciona un método Java para una función que se utiliza al ejecutar la expresión XQuery.

    XDynamicContext tiene dos métodos bindFunction. Cada uno de ellos requiere un objeto QName correspondiente al nombre de la función y un objeto Method que identifica el método Java que proporcionará la implementación de la función.
    Tabla 2. Métodos bindFunction de XDynamicContext.

    En esta tabla se explica cuándo se utiliza cada forma de los métodos bindFunction de XDynamicContext.

    Nombre del método Finalidad
    bindFunction(QName qname, Method method) Se utiliza cuando se enlaza un método estático
    bindFunction(QName qname, Method method, Object instanceObject) Se utiliza cuando se enlaza un método de instancia
    El ejemplo siguiente ejecuta la expresión XQuery preparada en el primer ejemplo, enlazado primero los métodos para las funciones que utiliza. En este ejemplo, los métodos estáticos atan, sin y toDegrees de la clase java.lang.Math se utilizan para proporcionar las implementaciones para las funciones externas.
    // Crear un nuevo contexto dinámico
    XDynamicContext dynamicContext = factory.newDynamicContext();
    
    // Retrieve the java.lang.reflect.Method object for the trig:toDegrees function
    Method toDegreesMethod = Math.class.getMethod("toDegrees", Double.TYPE);
    
    // Bind the function to the dynamic context
    dynamicContext.bindFunction(toDegreesQName, toDegreesMethod);
    
    // Create QNames for the trig:arctan and trig:sin functions
    QName arctanQName = new QName("http://www.example.org/trigonometry", "arctan");
    QName sinQName = new QName("http://www.example.org/trigonometry", "sin");
    
    // Retrieve the java.lang.reflect.Method objects for the trig:arctan and trig:sin functions
    // then bind them to the dynamic context
    Method arctanMethod = Math.class.getMethod("atan", Double.TYPE);
    Method sinMethod = Math.class.getMethod("sin", Double.TYPE);
    dynamicContext.bindFunction(arctanQName, arctanMethod);
    dynamicContext.bindFunction(sinQName, sinMethod);
    
    // Create an XML input document
    String xml = "<ramps>" +
    "<ramp><base>4</base><height>4</height></ramp>" +
    "<ramp><base>4</base><height>3</height></ramp>" +
    "<ramp><base>10</base><height>2</height></ramp>" +
    "</ramps>";
    StreamSource source = new StreamSource(new StringReader(xml));
    
    // Execute the query
    XSequenceCursor result = executable.execute(source, dynamicContext);
     
    // Serialize the result to System.out
    result.exportItem(new StreamResult(System.out));

Icon that indicates the type of topic Task topic



Timestamp icon Last updated: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=txml_funcs_xquery
File name: txml_funcs_xquery.html