4.3.3.5  Wikipedia Scrapper Applikation

In diesem Kapitel wollen wir eine XSLT Transformation bauen, die während des Durchlaufs durch einen XML Baum Anfragen an ein XQuery Skript auf einem MarkLogic Server stellt. Über einen GET Request wird ein Feld <title> zur Persistierung in einer ML Collection übertragen.

4.3.3.5.1  App Server Authentifizierung

Um dieses Szenario realisieren zu können, müssen wir die Rechte in MarkLogic so einstellen, dass Webrequests ohne eine Authentifizierung akzeptiert werden. D.h. unsere Applikation ist also eher für den internen Gebrauch gedacht.
Da momentan der Saxon XSLT Prozessor die Auflösung von URIs dem Java URI Resolver überlässt, dieser aber eine Authentifizierung mit Credentials in der URL, wie in
fn:json-to-xml('http://admin:admin@localhost:8088')
noch nicht unterstützt, müssen wir die Authentifizierung für unsere MarkLogic Webapp ausschalten.
Dazu setzen wir die Einstellung authentication unseres App Servers auf application-level und weisen die Default-User Rolle einem admin Benutzer zu.
In der App Server Konfiguration kann man die Stufe einstellen, auf der der Zugriffsmechanismus greifen soll. Hier stellen wir application-level mit einem Admin-User ein, um für das Intranet die Authentifizierung auszuschalten.

Bild: 16  MarkLogic App Server Authentifizierung einstellen
Eine ausgefeiltere Einstellung wird im Kapitel Dokument-Rechte in MarkLogic beschrieben.

4.3.3.5.2  XML Eingabe

Damit das Experiment etwas aufregender wird, arbeiten wir mittels XML Streaming auf einem Wikipedia Dump mit 5.3 GB Filesize ↗↗. Das XML dazu sieht folgendermassen aus:
<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
             xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ 
                                 http://www.mediawiki.org/xml/export-0.10.xsd" 
             version="0.10" 
             xml:lang="en">
    
   <siteinfo>
     <sitename>Wikipedia</sitename>
     <dbname>enwiki</dbname>
     <base>https://en.wikipedia.org/wiki/Main_Page</base>
     <generator>MediaWiki 1.29.0-wmf.12</generator>
     <case>first-letter</case>
     <namespaces>
       [...]
     </namespaces>
   </siteinfo>
   <page>
     <title>AccessibleComputing</title>
     <ns>0</ns>
     <id>10</id>
     <redirect title="Computer accessibility" />
     <revision>
       <id>631144794</id>
       <parentid>381202555</parentid>
       <timestamp>2014-10-26T04:50:23Z</timestamp>
       <contributor>
         <username>Paine Ellsworth</username>
         <id>9092818</id>
       </contributor>
[...]
Wir wollen alle Titel in einer Datenbank speichern, deshalb wird auf das <title> Element gematcht.

4.3.3.5.3  XSLT Transformation

Die Streaming Transformation mit dem Iterator Konzept sieht so aus:
template name="main">
  <xsl:source-document href="{$input-file}" streamable='yes'>
    <result>
      <xsl:iterate select="page/title">
        <xsl:variable name="json-call" select="json-to-xml(
                                               unparsed-text(
                                               concat($server-url,'/scrap-title.xqy?',
                                                      'title=',encode-for-uri(.))))"/>
        <state>
          <xsl:sequence select="$json-call/descendant::*[@key='state']/text()"/>
        </state>
      </xsl:iterate>
    </result>
  </xsl:source-document> 
</xsl:template>
Hier werden in einer Ergebnis Struktur mit einem <result> Element einzelne <state> Elemente ausgegeben.
Der Inhalt dieser Elemente ist Rückgabewert eines Webrequests über die Funktion fn:unparsed-text() .
An das Skript scrap-title.xqy wird ein Parameter title übergeben:
xquery version "1.0-ml";

import module namespace json = "http://marklogic.com/xdmp/json" 
                            at "/MarkLogic/json/json.xqy";

declare namespace local = 'local:';
declare variable $title := xdmp:get-request-field('title');

declare function local:render-response($response)
{
  xdmp:add-response-header("Pragma", "no-cache"),
  xdmp:add-response-header("Cache-Control", "no-cache"),
  xdmp:add-response-header("Expires", "0"),
  xdmp:set-response-content-type('text/json; charset=utf-8'),
  xdmp:unquote($response)
};

let $root := <title>{ $title }</title>,
$options :=
<options xmlns="xdmp:document-insert">  
  <permissions>{ xdmp:default-permissions() }</permissions>
  <collections>
    <collection>/wikimedia-titles</collection>
  </collections>
</options>,
$fname := concat('/wikimedia-titles/', xdmp:md5($title), ".xml"),
$td := xdmp:document-insert($fname, $root, $options)
return 
  local:render-response(concat('{"state":"success","title":"',$title,'"}'))
Wenn alles gut läuft, sollte die Transformation nach einer halben Stunde abgeschlossen sein. Es sollten sich in der
Collection /wikimedia-titles viele Einträge befinden, mit Dateinamen wie:
<fname>/wikimedia-titles/b00bb36cf9dd18f12141f463f59947e6.xml</fname>
Previous Page Next Page
Version: 93
Jan 25 2021