added proper namespace in example config
[idzebra-moved-to-github.git] / doc / recordmodel-domxml.xml
1 <chapter id="record-model-domxml">
2   <!-- $Id: recordmodel-domxml.xml,v 1.3 2007-02-20 14:57:00 marc Exp $ -->
3   <title>&dom; &xml; Record Model and Filter Module</title>
4
5   <para>
6    The record model described in this chapter applies to the fundamental,
7    structured &xml;
8    record type <literal>dom</literal>, introduced in
9    <xref linkend="componentmodulesdom"/>. The &dom; &xml; record model
10    is experimental, and it's inner workings might change in future
11    releases of the &zebra; Information Server.
12   </para>
13
14   
15   
16   <section id="record-model-domxml-filter">
17    <title>&dom; Record Filter</title>
18
19      <para>
20       The &dom; &xml; filter uses a standard &dom; &xml; structure as
21       internal data model, and can therefore parse, index, and display 
22       any &xml; document type. It is wellsuited to work on 
23       standardized &xml;-based formats such as Dublin Core, MODS, METS,
24       MARCXML, OAI-PMH, RSS, and performs equally  well on any other
25       non-standard &xml; format. 
26     </para>
27     <para>
28       A parser for binary &marc; records based on the ISO2709 library
29       standard is provided, it transforms these to the internal
30       &marcxml; &dom; representation. Other binary document parsers
31       are planned to follow.  
32     </para>
33    </section>
34
35
36    <section id="record-model-domxml-architecture">
37     <title>&dom; &xml; filter architecture</title>   
38
39     <para>
40       The internal &dom; &xml; representation can be fed into four
41       different pipelines, consisting of arbitraily many sucessive
42       &xslt; transformations.
43     </para>
44
45     <table id="record-model-domxml-architecture-table" frame="top">
46       <title>&dom; &xml; filter pipelines overview</title>
47       <tgroup cols="5">
48        <thead>
49         <row>
50          <entry>Name</entry>
51          <entry>When</entry>
52          <entry>Description</entry>
53          <entry>Input</entry>
54          <entry>Output</entry>
55         </row>
56        </thead>
57        
58        <tbody>
59         <row>
60          <entry><literal>input</literal></entry>
61          <entry>first</entry>
62          <entry>input parsing and initial
63           transformations to common &xml; format</entry>
64          <entry>raw &xml; record buffers, &xml;  streams and 
65                 binary &marc; buffers</entry>
66          <entry>single &dom; &xml; documents suitable for indexing and
67                 internal storage</entry>
68         </row>
69         <row>
70          <entry><literal>extract</literal></entry>
71          <entry>second</entry>
72          <entry>indexing term extraction
73           transformations</entry>
74          <entry>common single &dom; &xml; format</entry>
75          <entry>&zebra; internal indexing &dom; &xml; document</entry>
76         </row>
77         <row>
78          <entry><literal>store</literal></entry>
79          <entry>second</entry>
80          <entry> transformations before internal document
81           storage</entry>
82          <entry>common single &dom; &xml; format</entry>
83          <entry>&zebra; internal storage &dom; &xml; document</entry>
84         </row>
85         <row>
86          <entry><literal>retrieve</literal></entry>
87          <entry>third</entry>
88          <entry>document retrieve transformations from storage to output
89           syntax and format</entry>
90          <entry>&zebra; internal storage &dom; &xml; document</entry>
91          <entry>requested output syntax and format</entry>
92         </row>
93        </tbody>
94       </tgroup>
95      </table>
96
97     <para>
98       The &dom; &xml; filter pipelines use &xslt; (and if  supported on
99       your platform, even &exslt;), it brings thus full &xpath;
100       support to the indexing, storage and display rules of not only
101       &xml; documents, but also binary &marc; records.
102     </para>
103    </section>
104
105
106    <section id="record-model-domxml-pipeline">
107     <title>&dom; &xml; filter pipeline configuration</title>   
108
109    <para>
110     The experimental, loadable  &dom; &xml;/&xslt; filter module
111    <literal>mod-dom.so</literal> 
112     is invoked by the <filename>zebra.cfg</filename> configuration statement
113     <screen>
114      recordtype.xml: dom.db/filter_dom_conf.xml
115     </screen>
116     In this example on all data files with suffix 
117     <filename>*.xml</filename>, where the
118     &dom; &xslt; filter configuration file is found in the
119     path <filename>db/filter_dom_conf.xml</filename>.
120    </para>
121
122    <para>The &dom; &xslt; filter configuration file must be
123     valid &xml;. It might look like this:
124     <screen> 
125     <![CDATA[
126     <?xml version="1.0" encoding="UTF8"?>
127     <dom xmlns="http://indexdata.com/zebra-2.0">
128       <input syntax="xml">
129         <xmlreader level="1"/>
130       </input>
131       <extract name="index">
132          <xslt stylesheet="common2index.xsl"/>
133       </extract>
134       <store name="index">
135          <xslt stylesheet="common2store.xsl"/>
136       </store>
137       <retrieve name="dc">
138         <xslt stylesheet="store2dc.xsl"/>
139       </retrieve>
140     </dom>
141     ]]>
142     </screen>
143    </para>
144
145    <para>
146     All named stylesheets defined inside
147     <literal>schema</literal> element tags 
148     are for presentation after search, including
149     the indexing stylesheet (which is a great debugging help). The
150     names defined in the <literal>name</literal> attributes must be
151     unique, these are the literal <literal>schema</literal> or 
152     <literal>element set</literal> names used in 
153       <ulink url="http://www.loc.gov/standards/sru/srw/">&srw;</ulink>,
154       <ulink url="&url.sru;">&sru;</ulink> and
155     &z3950; protocol queries.
156     The paths in the <literal>stylesheet</literal> attributes
157     are relative to zebras working directory, or absolute to file
158     system root.
159    </para>
160    <para>
161     The <literal>&lt;split level="2"/&gt;</literal> decides where the
162     &xml; Reader shall split the
163     collections of records into individual records, which then are
164     loaded into &dom;, and have the indexing &xslt; stylesheet applied.
165    </para>
166    <para>
167     There must be exactly one indexing &xslt; stylesheet, which is
168     defined by the magic attribute  
169     <literal>identifier="http://indexdata.dk/zebra/xslt/1"</literal>.
170    </para>
171
172    <section id="record-model-domxml-internal">
173     <title>&dom; filter internal record representation</title>   
174     <para>When indexing, an &xml; Reader is invoked to split the input
175     files into suitable record &xml; pieces. Each record piece is then
176     transformed to an &xml; &dom; structure, which is essentially the
177     record model. Only &xslt; transformations can be applied during
178     index, search and retrieval. Consequently, output formats are
179     restricted to whatever &xslt; can deliver from the record &xml;
180     structure, be it other &xml; formats, HTML, or plain text. In case
181     you have <literal>libxslt1</literal> running with E&xslt; support,
182     you can use this functionality inside the &dom;
183     filter configuration &xslt; stylesheets.
184     </para>
185    </section>
186
187    <section id="record-model-domxml-canonical">
188     <title>&dom; Canonical Indexing Format</title>   
189     <para>The output of the indexing &xslt; stylesheets must contain
190     certain elements in the magic 
191      <literal>xmlns:z="http://indexdata.dk/zebra/xslt/1"</literal>
192     namespace. The output of the &xslt; indexing transformation is then
193     parsed using &dom; methods, and the contained instructions are
194     performed on the <emphasis>magic elements and their
195     subtrees</emphasis>.
196     </para>
197     <para>
198     For example, the output of the command
199      <screen>  
200       xsltproc xsl/oai2index.xsl one-record.xml
201      </screen> 
202      might look like this:
203      <screen>
204       &lt;?xml version="1.0" encoding="UTF-8"?&gt;
205       &lt;z:record xmlns:z="http://indexdata.dk/zebra/xslt/1" 
206            z:id="oai:JTRS:CP-3290---Volume-I" 
207            z:rank="47896"
208            z:type="update"&gt;
209        &lt;z:index name="oai_identifier" type="0"&gt;
210                 oai:JTRS:CP-3290---Volume-I&lt;/z:index&gt;
211        &lt;z:index name="oai_datestamp" type="0"&gt;2004-07-09&lt;/z:index&gt;
212        &lt;z:index name="oai_setspec" type="0"&gt;jtrs&lt;/z:index&gt;
213        &lt;z:index name="dc_all" type="w"&gt;
214           &lt;z:index name="dc_title" type="w"&gt;Proceedings of the 4th 
215                 International Conference and Exhibition:
216                 World Congress on Superconductivity - Volume I&lt;/z:index&gt;
217           &lt;z:index name="dc_creator" type="w"&gt;Kumar Krishen and *Calvin
218                 Burnham, Editors&lt;/z:index&gt;
219        &lt;/z:index&gt;
220      &lt;/z:record&gt;
221      </screen>
222     </para>
223     <para>This means the following: From the original &xml; file 
224      <literal>one-record.xml</literal> (or from the &xml; record &dom; of the
225      same form coming from a splitted input file), the indexing
226      stylesheet produces an indexing &xml; record, which is defined by
227      the <literal>record</literal> element in the magic namespace
228      <literal>xmlns:z="http://indexdata.dk/zebra/xslt/1"</literal>.
229      &zebra; uses the content of 
230      <literal>z:id="oai:JTRS:CP-3290---Volume-I"</literal> as internal
231      record ID, and - in case static ranking is set - the content of 
232      <literal>z:rank="47896"</literal> as static rank. Following the
233      discussion in <xref linkend="administration-ranking"/>
234      we see that this records is internally ordered
235      lexicographically according to the value of the string
236      <literal>oai:JTRS:CP-3290---Volume-I47896</literal>.
237      The type of action performed during indexing is defined by
238      <literal>z:type="update"&gt;</literal>, with recognized values
239      <literal>insert</literal>, <literal>update</literal>, and 
240      <literal>delete</literal>. 
241     </para>
242     <para>In this example, the following literal indexes are constructed:
243      <screen>
244        oai_identifier
245        oai_datestamp
246        oai_setspec
247        dc_all
248        dc_title
249        dc_creator
250      </screen>
251      where the indexing type is defined in the 
252      <literal>type</literal> attribute 
253      (any value from the standard configuration
254      file <filename>default.idx</filename> will do). Finally, any 
255      <literal>text()</literal> node content recursively contained
256      inside the <literal>index</literal> will be filtered through the
257      appropriate charmap for character normalization, and will be
258      inserted in the index.
259     </para>
260     <para>
261      Specific to this example, we see that the single word
262      <literal>oai:JTRS:CP-3290---Volume-I</literal> will be literal,
263      byte for byte without any form of character normalization,
264      inserted into the index named <literal>oai:identifier</literal>,
265      the text 
266      <literal>Kumar Krishen and *Calvin Burnham, Editors</literal>
267      will be inserted using the <literal>w</literal> character
268      normalization defined in <filename>default.idx</filename> into
269      the index <literal>dc:creator</literal> (that is, after character
270      normalization the index will keep the inidividual words 
271      <literal>kumar</literal>, <literal>krishen</literal>, 
272      <literal>and</literal>, <literal>calvin</literal>,
273      <literal>burnham</literal>, and <literal>editors</literal>), and
274      finally both the texts
275      <literal>Proceedings of the 4th International Conference and Exhibition:
276       World Congress on Superconductivity - Volume I</literal> 
277      and
278      <literal>Kumar Krishen and *Calvin Burnham, Editors</literal> 
279      will be inserted into the index <literal>dc:all</literal> using
280      the same character normalization map <literal>w</literal>. 
281     </para>
282     <para>
283      Finally, this example configuration can be queried using &pqf;
284      queries, either transported by &z3950;, (here using a yaz-client) 
285      <screen>
286       <![CDATA[
287       Z> open localhost:9999
288       Z> elem dc
289       Z> form xml
290       Z>
291       Z> f @attr 1=dc_creator Kumar
292       Z> scan @attr 1=dc_creator adam
293       Z>
294       Z> f @attr 1=dc_title @attr 4=2 "proceeding congress superconductivity"
295       Z> scan @attr 1=dc_title abc
296       ]]>
297      </screen>
298      or the proprietary
299      extentions <literal>x-pquery</literal> and
300      <literal>x-pScanClause</literal> to
301      &sru;, and &srw;
302      <screen>
303       <![CDATA[
304       http://localhost:9999/?version=1.1&operation=searchRetrieve&x-pquery=%40attr+1%3Ddc_creator+%40attr+4%3D6+%22the
305       http://localhost:9999/?version=1.1&operation=scan&x-pScanClause=@attr+1=dc_date+@attr+4=2+a
306       ]]>
307      </screen>
308      See <xref linkend="zebrasrv-sru"/> for more information on &sru;/&srw;
309      configuration, and <xref linkend="gfs-config"/> or the &yaz;
310      <ulink url="&url.yaz.cql;">&cql; section</ulink>
311      for the details or the &yaz; frontend server.
312     </para>
313     <para>
314      Notice that there are no <filename>*.abs</filename>,
315      <filename>*.est</filename>, <filename>*.map</filename>, or other &grs1;
316      filter configuration files involves in this process, and that the
317      literal index names are used during search and retrieval.
318     </para>
319    </section>
320   </section>
321
322
323   <section id="record-model-domxml-conf">
324    <title>&dom; Record Model Configuration</title>
325
326
327   <section id="record-model-domxml-index">
328    <title>&dom; Indexing Configuration</title>
329     <para>
330      As mentioned above, there can be only one indexing
331      stylesheet, and configuration of the indexing process is a synonym
332      of writing an &xslt; stylesheet which produces &xml; output containing the
333      magic elements discussed in  
334      <xref linkend="record-model-domxml-internal"/>. 
335      Obviously, there are million of different ways to accomplish this
336      task, and some comments and code snippets are in order to lead
337      our paduans on the right track to the  good side of the force.
338     </para>
339     <para>
340      Stylesheets can be written in the <emphasis>pull</emphasis> or
341      the <emphasis>push</emphasis> style: <emphasis>pull</emphasis>
342      means that the output &xml; structure is taken as starting point of
343      the internal structure of the &xslt; stylesheet, and portions of
344      the input &xml; are <emphasis>pulled</emphasis> out and inserted
345      into the right spots of the output &xml; structure. On the other
346      side, <emphasis>push</emphasis> &xslt; stylesheets are recursavly
347      calling their template definitions, a process which is commanded
348      by the input &xml; structure, and avake to produce some output &xml;
349      whenever some special conditions in the input styelsheets are
350      met. The <emphasis>pull</emphasis> type is well-suited for input
351      &xml; with strong and well-defined structure and semantcs, like the
352      following &oai; indexing example, whereas the
353      <emphasis>push</emphasis> type might be the only possible way to
354      sort out deeply recursive input &xml; formats.
355     </para>
356     <para> 
357      A <emphasis>pull</emphasis> stylesheet example used to index
358      &oai; harvested records could use some of the following template
359      definitions:
360      <screen>
361       <![CDATA[
362       <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
363        xmlns:z="http://indexdata.dk/zebra/xslt/1"
364        xmlns:oai="http://www.openarchives.org/&oai;/2.0/" 
365        xmlns:oai_dc="http://www.openarchives.org/&oai;/2.0/oai_dc/" 
366        xmlns:dc="http://purl.org/dc/elements/1.1/"
367        version="1.0">
368
369        <xsl:output indent="yes" method="xml" version="1.0" encoding="UTF-8"/>
370
371         <!-- disable all default text node output -->
372         <xsl:template match="text()"/>
373
374          <!-- match on oai xml record root -->
375          <xsl:template match="/">    
376           <z:record z:id="{normalize-space(oai:record/oai:header/oai:identifier)}" 
377            z:type="update">
378            <!-- you might want to use z:rank="{some &xslt; function here}" --> 
379            <xsl:apply-templates/>
380           </z:record>
381          </xsl:template>
382
383          <!-- &oai; indexing templates -->
384          <xsl:template match="oai:record/oai:header/oai:identifier">
385           <z:index name="oai_identifier" type="0">
386            <xsl:value-of select="."/>
387           </z:index>    
388          </xsl:template>
389
390          <!-- etc, etc -->
391
392          <!-- DC specific indexing templates -->
393          <xsl:template match="oai:record/oai:metadata/oai_dc:dc/dc:title">
394           <z:index name="dc_title" type="w">
395            <xsl:value-of select="."/>
396           </z:index>
397          </xsl:template>
398
399          <!-- etc, etc -->
400  
401       </xsl:stylesheet>
402       ]]>
403      </screen>
404     </para>
405     <para>
406      Notice also,
407      that the names and types of the indexes can be defined in the
408      indexing &xslt; stylesheet <emphasis>dynamically according to
409      content in the original &xml; records</emphasis>, which has
410      opportunities for great power and wizardery as well as grande
411      disaster.  
412     </para>
413     <para>
414      The following excerpt of a <emphasis>push</emphasis> stylesheet
415      <emphasis>might</emphasis> 
416      be a good idea according to your strict control of the &xml;
417      input format (due to rigerours checking against well-defined and
418      tight RelaxNG or &xml; Schema's, for example):
419      <screen>
420       <![CDATA[
421       <xsl:template name="element-name-indexes">     
422        <z:index name="{name()}" type="w">
423         <xsl:value-of select="'1'"/>
424        </z:index>
425       </xsl:template>
426       ]]>
427      </screen>
428      This template creates indexes which have the name of the working 
429      node of any input  &xml; file, and assigns a '1' to the index.
430      The example query 
431      <literal>find @attr 1=xyz 1</literal> 
432      finds all files which contain at least one
433      <literal>xyz</literal> &xml; element. In case you can not control
434      which element names the input files contain, you might ask for
435      disaster and bad karma using this technique.
436     </para>
437     <para>
438      One variation over the theme <emphasis>dynamically created
439      indexes</emphasis> will definitely be unwise:
440      <screen>
441       <![CDATA[  
442       <!-- match on oai xml record root -->
443       <xsl:template match="/">    
444        <z:record z:type="update">
445       
446         <!-- create dynamic index name from input content --> 
447         <xsl:variable name="dynamic_content">
448          <xsl:value-of select="oai:record/oai:header/oai:identifier"/>
449         </xsl:variable>
450         
451         <!-- create zillions of indexes with unknown names -->
452         <z:index name="{$dynamic_content}" type="w">
453          <xsl:value-of select="oai:record/oai:metadata/oai_dc:dc"/>
454         </z:index>          
455        </z:record>
456        
457       </xsl:template>
458       ]]>
459      </screen>
460      Don't be tempted to cross
461      the line to the dark side of the force, paduan; this leads
462      to suffering and pain, and universal
463      disentigration of your project schedule.
464     </para>
465   </section>
466
467   <section id="record-model-domxml-elementset">
468    <title>&dom; Exchange Formats</title>
469    <para>
470      An exchange format can be anything which can be the outcome of an
471      &xslt; transformation, as far as the stylesheet is registered in
472      the main &dom; &xslt; filter configuration file, see
473      <xref linkend="record-model-domxml-filter"/>.
474      In principle anything that can be expressed in  &xml;, HTML, and
475      TEXT can be the output of a <literal>schema</literal> or 
476     <literal>element set</literal> directive during search, as long as
477      the information comes from the 
478      <emphasis>original input record &xml; &dom; tree</emphasis>
479      (and not the transformed and <emphasis>indexed</emphasis> &xml;!!).
480     </para>
481     <para>
482      In addition, internal administrative information from the &zebra;
483      indexer can be accessed during record retrieval. The following
484      example is a summary of the possibilities:
485      <screen>
486       <![CDATA[  
487       <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
488        xmlns:z="http://indexdata.dk/zebra/xslt/1"
489        version="1.0">
490
491        <!-- register internal zebra parameters -->       
492        <xsl:param name="id" select="''"/>
493        <xsl:param name="filename" select="''"/>
494        <xsl:param name="score" select="''"/>
495        <xsl:param name="schema" select="''"/>
496            
497        <xsl:output indent="yes" method="xml" version="1.0" encoding="UTF-8"/>
498
499        <!-- use then for display of internal information -->
500        <xsl:template match="/">
501          <z:zebra>
502            <id><xsl:value-of select="$id"/></id>
503            <filename><xsl:value-of select="$filename"/></filename>
504            <score><xsl:value-of select="$score"/></score>
505            <schema><xsl:value-of select="$schema"/></schema>
506          </z:zebra>
507        </xsl:template>
508
509       </xsl:stylesheet>
510       ]]>
511      </screen>
512     </para>
513
514   </section>
515
516   <section id="record-model-domxml-example">
517    <title>&dom; Filter &oai; Indexing Example</title>
518    <para>
519      The sourcecode tarball contains a working &dom; filter example in
520      the directory <filename>examples/dom-oai/</filename>, which
521      should get you started.  
522     </para>
523     <para>
524      More example data can be harvested from any &oai; complient server,
525      see details at the  &oai; 
526      <ulink url="http://www.openarchives.org/">
527       http://www.openarchives.org/</ulink> web site, and the community
528       links at 
529      <ulink url="http://www.openarchives.org/community/index.html">
530       http://www.openarchives.org/community/index.html</ulink>.
531      There is a  tutorial
532      found at
533      <ulink url="http://www.oaforum.org/tutorial/">
534       http://www.oaforum.org/tutorial/</ulink>.
535     </para>
536    </section>
537
538   </section>
539
540   
541  </chapter>
542
543
544 <!--
545
546 c)  Main "dom" &xslt; filter config file:
547   cat db/filter_dom_conf.xml 
548
549   <?xml version="1.0" encoding="UTF8"?>
550   <schemaInfo>
551     <schema name="dom" stylesheet="db/dom2dom.xsl" />
552     <schema name="index" identifier="http://indexdata.dk/zebra/xslt/1"
553             stylesheet="db/dom2index.xsl" />
554     <schema name="dc" stylesheet="db/dom2dc.xsl" />
555     <schema name="dc-short" stylesheet="db/dom2dc_short.xsl" />
556     <schema name="snippet" snippet="25" stylesheet="db/dom2snippet.xsl" />
557     <schema name="help" stylesheet="db/dom2help.xsl" />
558     <split level="1"/>
559   </schemaInfo>
560
561   the paths are relative to the directory where zebra.init is placed
562   and is started up.
563
564   The split level decides where the SAX parser shall split the
565   collections of records into individual records, which then are
566   loaded into &dom;, and have the indexing &xslt; stylesheet applied.
567
568   The indexing stylesheet is found by it's identifier.
569
570   All the other stylesheets are for presentation after search.
571
572 - in data/ a short sample of harvested carnivorous plants
573   ZEBRA_INDEX_DIRS=data/carnivor_20050118_2200_short-346.xml
574
575 - in root also one single data record - nice for testing the xslt
576   stylesheets,
577   
578   xsltproc db/dom2index.xsl carni*.xml
579
580   and so on.
581
582 - in db/ a cql2pqf.txt yaz-client config file 
583   which is also used in the yaz-server <ulink url="&url.cql;">&cql;</ulink>-to-&pqf; process
584
585    see: http://www.indexdata.com/yaz/doc/tools.tkl#tools.cql.map
586
587 - in db/ an indexing &xslt; stylesheet. This is a PULL-type XSLT thing,
588   as it constructs the new &xml; structure by pulling data out of the
589   respective elements/attributes of the old structure.
590
591   Notice the special zebra namespace, and the special elements in this
592   namespace which indicate to the zebra indexer what to do.
593
594   <z:record id="67ht7" rank="675" type="update">
595   indicates that a new record with given id and static rank has to be updated. 
596
597   <z:index name="title" type="w">
598    encloses all the text/&xml; which shall be indexed in the index named
599    "title" and of index type "w" (see  file default.idx in your zebra
600    installation) 
601
602
603    </para>
604
605    <para>
606 -->
607
608
609
610
611  <!-- Keep this comment at the end of the file
612  Local variables:
613  mode: sgml
614  sgml-omittag:t
615  sgml-shorttag:t
616  sgml-minimize-attributes:nil
617  sgml-always-quote-attributes:t
618  sgml-indent-step:1
619  sgml-indent-data:t
620  sgml-parent-document: "zebra.xml"
621  sgml-local-catalogs: nil
622  sgml-namecase-general:t
623  End:
624  -->