Externe Funktionen mit XQuery verwenden
Wenn Sie mit einem XQuery-Ausdruck arbeiten, der externe Funktionen verwendet, deklarieren Sie die Funktionssignaturen im XQuery-Prolog als externe Funktionen oder deklarieren Sie sie mit einer XStaticContext-Instanz. Verwenden Sie für jede Funktion eine XDynamicContext-Instanz, um eine Java-Implementierung bereitzustellen (bzw. zu binden).
Vorgehensweise
- Wenn Sie einen XQuery-Ausdruck erstellen, der externe Funktionen verwendet,
deklarieren Sie die Funktionssignaturen im XQuery-Prolog oder mithilfe
einer
XStaticContext-Instanz.
In XStaticContext deklarierte Funktionen sind nur für das Hauptmodul sichtbar. Wenn eine extern Funktionen für ein Bibliotheksmodul sichtbar sein soll, muss die Funktion im Prolog dieses Bibliotheksmoduls deklariert werden.
Die Schnittstelle "XStaticContext" stellt zwei declareFunction-Methoden mit jeweils drei Parametern bereit, einem Parameter für den Namen, einem für den Rückgabetyp der Funktion und einem für ein Array mit den Typen der Argumente. Der Name wird immer als ein QName-Objekt angegeben. Der Typ kann jedoch ein QName oder XSequenceType sein. Der Funktionsname, der Rückgabetyp und die Argumenttypen müssen eine eindeutige Identifizierung der Funktion ermöglichen.
Tabelle 1. declareFunction-Methoden von XStaticContext. In der folgenden Tabelle ist die Verwendung der einzelnen Varianten der Methode declareFunction erläutert.
Methodensignatur Zweck declareFunction(QName name, QName type, QName[] argTypes) Verwendung, wenn der Rückgabewert und die Argumente der Funktion ausschließlich einzelne atomare Werte sind QNames für die Typen müssen auf integrierte Typen verweisen oder auf globale Typen, die in einem Schema deklariert sind, das in der für die Erstellung der XStaticContext-Instanz verwendeten XFactory-Instanz registriert ist. Wenn ein QName auf einen nicht atomaren Typ verweist, behandelt der Prozessor ihn so, als wäre er vom Typ element(*, ns:type). Hier steht ns:type für den gegebenen QName. In der Schnittstelle "XTypeConstants" sind komfortable Konstanten verfügbar, die für jeden integrierten Typ ein QName-Objekt bereitstellen.
declareFunction(QName name, XSequenceType type, XSequenceType[] argTypes) Verwendung, wenn eines der Argumente oder der Rückgabewert der Funktion ein Knoten oder eine Sequenz atomarer Werte bzw. Knoten ist Der folgende XQuery-Ausdruck verwendet drei Funktionen, von denen zwei im Prolog deklariert sind.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>
Ist diese Abfrage beispielsweise über das xquerySource-Source-Objekt verfügbar, bereitet der folgende Code die Abfrage vor. Die nicht in der eigentlichen Abfrage deklarierte Funktion trig:toDegrees wird in der XStaticContext-Instanz deklariert.// Factory erstellen XFactory factory = XFactory.newInstance(); // Neuen statischen Kontext erstellen XStaticContext staticContext = factory.newStaticContext(); // Namespace für die Funktionen deklarieren staticContext.declareNamespace("trig", "http://www.example.org/trigonometry"); // QName für die Funktion trig:toDegrees erstellen QName toDegreesQName = new QName("http://www.example.org/trigonometry", "toDegrees"); // Funktion im statischen Kontext deklarieren staticContext.declareFunction(toDegreesQName, XTypeConstants.DOUBLE_QNAME, new QName[]{XTypeConstants.DOUBLE_QNAME}); // Ausführbares XQuery-Objekt für die Abfrage erstellen XQueryExecutable executable = factory.prepareXQuery(xquerySource, staticContext);
- Wenn Sie einen XQuery-Ausdruck ausführen, der externe Funktionen verwendet, geben Sie
mit einer XDynamicContext-Instanz die Java-Methoden an, die die Funktionen implementieren, bzw. binden Sie diese Java-Methoden mit der genannten Instanz.
Die Bindungen für externe Funktionen stehen dem Hauptmodul und allen Bibliotheksmodulen zur Verfügung, die eine Deklaration für diese Funktion in ihrem Prolog enthalten.
Verwenden Sie die Java-Darstellung, um ein Objekt java.lang.reflect.Method für die Funktion zu erhalten. Handelt es sich bei der Methode um eine Instanzmethode, ist zum Binden dieser Funktion ein Instanzobjekt erforderlich.
Ist für eine bei Ausführung des XQuery-Ausdrucks verwendete Funktion keine Java-Methode angegeben, tritt ein Fehler auf.
XDynamicContext stellt zwei bindFunction-Methoden bereit. Jede dieser Methoden erfordert ein QName-Objekt, das dem Namen der Funktion entspricht, und ein Methodenobjekt, das die Java-Methode bezeichnet, die die Implementierung der Funktion zur Verfügung stellt.Tabelle 2. bindFunction-Methoden von XDynamicContext. In der folgenden Tabelle ist die Verwendung der einzelnen Varianten der bindFunction-Methoden von XDynamicContext erläutert.
Methodenname Zweck bindFunction(QName qname, Method method) Verwendung, wenn eine statische Methode gebunden werden soll bindFunction(QName qname, Method method, Object instanceObject) Verwendung, wenn eine Instanzmethode gebunden werden soll Im folgenden Beispiel wird der im ersten Beispiel erstellte XQuery-Ausdruck ausgeführt. Dabei werden zunächst Methoden für die verwendeten Funktionen gebunden. In diesem Beispiel werden mit den statischen Methoden atan, sin und toDegrees der Klasse java.lang.Math die Implementierungen für die externen Funktionen bereitgestellt.// Neuen dynamischen Kontext erstellen XDynamicContext dynamicContext = factory.newDynamicContext(); // Objekt java.lang.reflect.Method für die Funktion trig:toDegrees abrufen Method toDegreesMethod = Math.class.getMethod("toDegrees", Double.TYPE); // Funktion an den dynamischen Kontext binden dynamicContext.bindFunction(toDegreesQName, toDegreesMethod); // QNames für die Funktionen trig:arctan und trig:sin erstellen QName arctanQName = new QName("http://www.example.org/trigonometry", "arctan"); QName sinQName = new QName("http://www.example.org/trigonometry", "sin"); // java.lang.reflect.Method-Objekte für die Funktionen trig:arctan und trig:sin abrufen // und dann an den dynamischen Kontext binden Method arctanMethod = Math.class.getMethod("atan", Double.TYPE); Method sinMethod = Math.class.getMethod("sin", Double.TYPE); dynamicContext.bindFunction(arctanQName, arctanMethod); dynamicContext.bindFunction(sinQName, sinMethod); // XML-Eingabedokument erstellen 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)); // Abfrage ausführen XSequenceCursor result = executable.execute(source, dynamicContext); // Ergebnis in System.out serialisieren result.exportItem(new StreamResult(System.out));
Unterartikel
In Abfragen deklarierte externe Funktionen mit XQuery verwenden
Ale Alternative zur Bindung von Java-Methoden an Funktionen in einer Abfrage über die API können externe Java-Funktionen direkt in einer Abfrage deklariert werden. Die einzige zusätzlich erforderliche Konfiguration ist, dass während der Abfrageausführung gebundene Java-Klassen im Klassenpfad vorhanden sind.


http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=txml_funcs_xquery
Dateiname:txml_funcs_xquery.html