4.1.7  Webservice Calls mit doc() und unparsed-text()

Eine verbreitete Paxis ist es, mit der Funktion document() oder kurz doc() entfernte Ressourcen in die Transformation einzubinden. Bei einer Schematron-Validierung, würde bspw. eine Regel, wie:
<sch:not-assert id="personal-check"
    role="error"
    test="doc(concat('https://tekturcms.de/personal.xqy?personal-id=',personal-id))/kuendigung">
        Angestellter mit ID "<sch:value-of select="personal-id"/>" hat gekündigt!
</sch:not-assert>
einen entferneten Webservice aufrufen und prüfen, ob für den Angestellten mit personal-id eine Kündigung vorliegt. Ist dies der Fall, so ist die negative Zusicherung not-assert nicht erfüllt, und die Schematron Regel feuert - was sich wohl im einfachsten Fall in einem Logfile Eintrag äussern sollte.
Was vermutlich viele noch nicht kennen - ich nehme jetzt einfach mal an, dass mein bisheriger Kenntnisstand dem der Mehrheit der XML-Entwickler entspricht - ist der Umstand, dass auch die Funktion unparsed-text() eine URL als Parameter nimmt:
<xsl:template match="angestellter"
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
        <hat-gekuendigt>
            <xsl:sequence select="json-to-xml(
                                  unparsed-text(
                                  concat('https://tekturcms.de/personal.xqy?personal-id=',
                                  personal-id))))/descendant::*[@key='gekuendigt']/text()"/>
        </hat-gekuendigt>
    </xsl:copy>
</xsl:template>
Während mit doc() oder document() ein zurückgeliefertes XML Fragment prozessiert wird, erwartet unparsed-text() z.B. einen JSON-String, der dann mittels der Funktion json-to-xml() nach XML konvertiert werden kann.
Beispielsweise könnte die Gegenseite zum angestellter Template mittels XQuery folgendermassen realisiert sein:
xquery version "1.0-ml";

declare variable $personal-id := xdmp:get-request-field('personal-id');

let $gekuendigt := if (collection('/personal')/*[personal-id = $personal-id and 
                                                 fn:exists(kuendingung)] then 
                                                 'ja' else 'nein'
return 
    common:render-response(concat('{"gekuendigt":"',$gekuendigt,'",
                                    "personal-id":"',$personal-id,'"}'))
Das zurückgeklieferte JSON Dokument sieht dann so aus:
{"gekuendig":"ja","personal-id":"q5687500"}
Konvertiert nach XML erhält man eine Map Struktur:
<map xmlns="http://www.w3.org/2005/xpath-functions">
    <string key="gekuedigt">ja</string>
    <string key="personal-id">q5687500</string>
</map>
was den Selektorausdruck im obigen XPATH erklärt:
json-to-xml(
unparsed-text(
concat('https://tekturcms.de/personal.xqy?personal-id=',
personal-id))))/descendant::*[@key='gekuendigt']/text()
Resultat der Konvertierung wäre - wie erwartet - ein um das gekuendigt Flag erweitertes <angestellter> Element:
<angestellter>
    <perosnal-id>q5687500</perosnal-id>
    <name>Alex</name>
    [...]
    <gekuendigt>nein</gekuendigt>
</angestellter>
Sicherlich wird der XML Entwickler eine XML Datenbank, wie MarkLogic, vorziehen und sich gleich XML Fragmente ausliefern laasen. Tektur ist aber bspw. mit MongoDB ↗↗ realisiert, die auf JSON arbeitet... Nicht zuletzt deshalb finde ich JSON Verarbeitung mit XSLT recht spannend.
Previous Page Next Page
Version: 92
Dec 26 2020