*** empty log message ***
[idzebra-moved-to-github.git] / doc / zebra.sgml
1 <!doctype linuxdoc system>
2
3 <!--
4   $Id: zebra.sgml,v 1.10 1995-12-13 13:45:21 quinn Exp $
5 -->
6
7 <article>
8 <title>Zebra Server - Administrators's Guide and Reference
9 <author>Index Data, <tt/info@index.ping.dk/
10 <date>$Revision: 1.10 $
11 <abstract>
12 The Zebra information server combines a versatile fielded/free-text
13 search engine with a Z39.50-1995 frontend to provide a powerful and flexible
14 information management system. This document explains the procedure for
15 installing and configuring the system, and outlines the possibilities
16 for managing data and providing Z39.50
17 services using the software.
18 </abstract>
19
20 <toc>
21
22 <sect>Introduction
23
24 <sect1>Overview
25
26 <p>
27 The Zebra system is a fielded free-text indexing and retrieval engine with a
28 Z39.50 frontend. You can use any commercial or freeware Z39.50 client
29 to access data stored in Zebra.
30
31 The Zebra server is our first step towards the development of a fully
32 configurable, open information system. Eventually, it will be paired
33 off with a powerful Z39.50 client to support complex information
34 management tasks within almost any application domain. We're making
35 the server available now because it's no fun to be in the open
36 information retrieval business all by yourself. We want to allow
37 people with interesting data to make their things
38 available in interesting ways, without having to start out
39 by implementing yet another protocol stack from scratch.
40
41 This document is an introduction to the Zebra system. It will tell you
42 how to compile the software, and how to prepare your first database.
43 It also explains how the server can be configured to give you the
44 functionality that you need.
45
46 You should read <it/Specifying and Using Application (Database)
47 Profiles/, which is bundled with the YAZ documentation, to learn how
48 records are formatted, and how you can configure Zebra to handle
49 different types of Z39.50 application profiles.
50
51 If you are interested in using the software, you should join the support
52 mailing-list by sending Email to <tt/zebra-request@index.ping.dk/.
53
54 <sect1>Features
55
56 <p>
57 This is a listing of some of the most important features of the
58 system.
59
60 <itemize>
61
62 <item>
63 Supports updating - records can be added and deleted without
64 rebuilding the index from scratch.
65 The update procedure is tolerant to crashes or hard interrupts
66 during register updating - registers can be reconstructed following a crash.
67 Registers can be safely updated even while users are accessing the server.
68
69 <item>
70 Supports large databases - files for indices, etc. can be
71 automatically partitioned over multiple disks.
72
73 <item>
74 Supports arbitrarily complex records - base input format is an
75 SGML-like syntax which allows nested (structured) data elements, as
76 well as variant forms of data.
77
78 <item>
79 Supports boolean queries as well as relevance-ranking (free-text)
80 searching. Right truncation and masking in terms are supported, as
81 well as full regular expressions.
82
83 <item>
84 Supports multiple concrete syntaxes
85 for record exchange (depending on the configuration): GRS-1, SUTRS,
86 ISO2709 (*MARC). Records can be mapped between record syntaxes and
87 schema on the fly.
88
89 <item>
90 Protocol support:
91
92 <itemize>
93
94 <item>
95 Protocol facilities: Init, Search, Retrieve, Browse.
96
97 <item>
98 Piggy-backed presents are honored in the search-request.
99
100 <item>
101 Named result sets are supported.
102
103 <item>
104 Easily configured to support different application profiles, with
105 tables for attribute sets, tag sets, and abstract syntaxes.
106 Additional tables control facilities such as element mappings to
107 different schema (eg., GILS-to-USMARC).
108
109 <item>
110 Complex composition specifications using Espec-1 are partially
111 supported (simple element requests only).
112
113 <item>
114 Element Set Names are established the Espec-1 capability of the
115 system, and are given in configuration files as simple element
116 requests (and possibly variant requests).
117
118 <item>
119 Some variant support (not fully implemented yet).
120
121 <item>
122 Using the YAZ toolkit for the protocol implementation, the
123 server can utilise a plug-in XTI/mOSI implementation (not included) to
124 provide SR services over an OSI stack, as well as Z39.50 over TCP/IP.
125
126 </itemize>
127
128 </itemize>
129
130 <sect1>Future Work
131
132 <p>
133 This is an alfa-release of the software, to allow you to look at
134 it - try it out, and assess whether it can be of use to you. We expect
135 this version to be followed by a succession of beta-releases until we
136 arrive at a stable first version.
137
138 These are some of the plans that we have for the software in the near
139 and far future, approximately ordered after their relative importance.
140 Items marked with an
141 asterisk will be implemented before the
142 last beta release.
143
144 <itemize>
145
146 <item>
147 *Allow the system to handle other input formats. Specifically
148 MARC records and general, structured ASCII records (such as mail/news
149 files) parameterized by regular expressions.
150
151 <item>
152 *Complete the support for variants. Finalize support for the WAIS
153 retrieval methodology.
154
155 <item>
156 *Finalize the data element <it/include/ facility to support multimedia
157 data elements in records.
158
159 <item>
160 *Port the system to Windows NT.
161
162 <item>
163 Add index and data compression to save disk space.
164
165 <item>
166 Add more sophisticated relevance ranking mechanisms. Add support for soundex
167 and stemming. Add relevance feedback support.
168
169 <item>
170 Add Explain support.
171
172 <item>
173 Add support for very large records by implementing segmentation and/or
174 variant pieces.
175
176 <item>
177 Support the Item Update extended service of the protocol.
178
179 <item>
180 The Zebra search engine supports approximate string matching in the
181 index. We'd like to find a way to support and control this from RPN.
182
183 <item>
184 We want to add a management system that allows you to
185 control your databases and configuration tables from a graphical
186 interface. We'll probably use Tcl/Tk to stay platform-independent.
187
188 </itemize>
189
190 Programmers thrive on user feedback. If you are interested in a facility that
191 you don't see mentioned here, or if there's something you think we
192 could do better, please drop us a mail. If you think it's all really
193 neat, you're of course welcome to drop us a line saying that, too.
194
195 <sect>Introduction
196
197 <sect>Compiling the software
198
199 <p>
200 Zebra uses the YAZ package to implement Z39.50, so you
201 have to compile YAZ before going further. Specifically, Zebra uses
202 the YAZ header files in <tt>yaz/include/..</tt> and its public library
203 <tt>yaz/lib/libyaz.a</tt>.
204
205 As with YAZ, an ANSI C compiler is required in order to compile the Zebra
206 server system &mdash; GNU C works fine.
207
208 Unpack the Zebra software. You might put Zebra in the same directory level
209 as YAZ, for example if YAZ is placed in ..<tt>/src/yaz-xxx</tt>, then
210 Zebra is placed in ..<tt>/src/zebra-yyy</tt>.
211
212 Edit the top-level <tt>Makefile</tt> in the Zebra directory in which
213 you specify the location of YAZ by setting make variables.
214 The <tt>OSILIB</tt> should be empty if YAZ wasn't compiled with
215 MOSI support. Some systems, such as Solaris, have separate socket
216 libraries and for those systems you need to specify the
217 <tt>NETLIB</tt> variable.
218
219 When you are done editing the <tt>Makefile</tt> type:
220 <tscreen><verb>
221 $ make
222 </verb></tscreen>
223
224 If successful, two executables have been created in the sub-directory
225 <tt/index/.
226 <descrip>
227 <tag><tt>zebrasrv</tt></tag> The Z39.50 server and search engine.
228 <tag><tt>zebraidx</tt></tag> The administrative tool for the search index.
229 </descrip>
230
231 <sect>Quick Start
232
233 <p>
234 This section will get you started quickly! We will try to index a few sample
235 GILS records that are included with the Zebra distribution. Go to the
236 <tt>test</tt> subdirectory. There you will find a configuration
237 file named <tt>zebra.cfg</tt> with the following contents:
238 <tscreen><verb>
239 # Where are the YAZ tables located.
240 profilePath: /usr/local/yaz
241
242 # Files that describe the attribute sets supported.
243 attset: bib1.att
244 attset: gils.att
245 </verb></tscreen>
246
247 Now, edit the file and set <tt>profilePath</tt> to the path of the
248 YAZ profile tables (sub directory <tt>tab</tt> of YAZ).
249
250 The 48 test records are located in the sub directory <tt>records</tt>.
251 To index these, type:
252 <tscreen><verb>
253 $ ../index/zebraidx -t grs update records
254 </verb></tscreen>
255
256 In the command above the option <tt>-t</tt> specified the record
257 type &mdash; in this case <tt>grs</tt>. The word <tt>update</tt> followed
258 by a directory root updates all files below that directory node.
259
260 If your indexing command went successful, you are now ready to
261 fire up a server. To start a server on port 2100, type:
262 <tscreen><verb>
263 $ ../index/zebrasrv tcp:@:2100
264 </verb></tscreen>
265
266 The Zebra index that you've just made has one database called Default. It will
267 return either USMARC, GRS-1, or SUTRS depending on what your client asks
268 for.
269
270 To test the server, you can use any Z39.50 client (1992 or later). For
271 instance, you can use the demo client that comes with YAZ: Just cd to
272 the <tt/client/ subdirectory of the YAZ distribution and type:
273
274 <tscreen><verb>
275 $ client tcp:localhost:2100
276 </verb></tscreen>
277
278 When the client has connected, you can type:
279
280 <tscreen><verb>
281 Z> find surficial
282 Z> show 1
283 </verb></tscreen>
284
285 The default retrieval syntax for the client is USMARC. To try other
286 formats for the same record, try:
287
288 <tscreen><verb>
289 Z>format sutrs
290 Z>show 1
291 Z>format grs-1
292 Z>show 1
293 </verb></tscreen>
294
295 If you've made it this far, there's a reasonably good chance that
296 you've made it through the compilation OK.
297
298 <sect>Administrating Zebra
299
300 <p>
301
302 Unlike many other retrieval systems, Zebra offers incremental
303 modifications of an existing index. Needless to say, these facilities
304 make the administration of Zebra a bit more complicated than
305 systems that use the &dquot;index-it-all&dquot; approach.
306
307 Normally, when Zebra modifies the index it reads a number of records
308 that you specify.
309 Depending on your specifications and on the contents of each record
310 one the following events take place for each record:
311 <descrip>
312 <tag>Insert</tag> The record is indexed as if it never occurred
313 before. Either the Zebra system doesn't know how to identify the record or
314 Zebra can identify the record but didn't find it to be already indexed.
315 <tag>Modify</tag> The record has already been indexed. In this case
316 either the contents of the record or the location (file) of the record
317 indicates that it has been indexed before.
318 <tag>Delete</tag> The record is deleted from the index. As in the
319 update-case it must be able to identify the record.
320 </descrip>
321
322 Please note that in both the modify- and delete- case the Zebra
323 indexer must be able to make a unique key that identifies the record in
324 question.
325
326 To administrate the Zebra retrieval system, you run the
327 <tt>zebraidx</tt> program. This program supports a number of options
328 which are preceded by a minus, and a few commands (not preceded by
329 minus).
330
331 Both the Zebra administrative tool and the Z39.50 server share a
332 set of index files and a global configuration file. The
333 name of the configuration file defaults to <tt>zebra.cfg</tt>.
334 The configuration file includes specifications on how to index
335 various kinds of records and where the other configuration files
336 are located. <tt>zebrasrv</tt> and <tt>zebraidx</tt> <em>must</em>
337 be run in the same directory where the configuration file if you do
338 not indicate the location of the configuration file by option
339 <tt>-c</tt>.
340
341 <sect1>Record types
342 <p>
343 Indexing is a record-per-record process, in which
344 either insert/modify/delete will occur. Before a record is indexed
345 search keys are extracted from whatever might be the layout the
346 original record (sgml,html,text, etc..). The Zebra system 
347 currently only supports SGML-like, structured records and unstructured text
348 records.
349 To specify a particular extraction process, use either the
350 command line option <tt>-t</tt> or specify a
351 <tt>recordType</tt> setting in the configuration file.
352
353 <sect1>The Zebra Configuration File
354 <p>
355 The Zebra configuration file, read by <tt>zebraidx</tt> and
356 <tt>zebrasrv</tt> defaults to <tt>zebra.cfg</tt> unless specified
357 by <tt>-c</tt> option.
358
359 You can edit the configuration file with a normal text editor.
360 Setting names and values are seperated by colons in the file. Lines
361 starting with a hash sign (<tt/#/) are treated as comments.
362
363 A set of records that share common characteristics are called a group.
364 When <tt>zebraidx</tt> is run and you wish to address a given group
365 you specify that group with the <tt>-g</tt> option. In this case
366 settings that have the group name as their prefix will be used
367 by <tt>zebraidx</tt> and not default values. The default values have no prefix.
368
369 The group is written before the option itself separated by a dot.
370 For instance, to set the record type for group <tt/public/ to <tt/grs/ (structured records)
371 you would write:
372
373 <tscreen><verb>
374 public.recordType: grs
375 </verb></tscreen>
376
377 To set the default value of the record type to text write:
378
379 <tscreen><verb>
380 recordType: text
381 </verb></tscreen>
382
383 The configuration settings are summarized below. They will be
384 explained further in the following sections.
385
386 <descrip>
387 <tag><it>group</it>recordType<it>name</it></tag>
388  Specifies how records with the file extension <it>name</it> should
389  be handled by the indexer. This option may also be specified
390  as a command line option (<tt>-t</tt>).
391 <tag><it>group</it>recordId</tag>
392  Specifies how the record is to be identified when updated.
393 <tag><it>group</it>database</tag>
394  Specifies the Z39.50 database.
395 <tag><it>group</it>storeKeys</tag>
396  Specifies whether key information should be saved for a given
397  group of records. If you plan to update/delete this type of
398  records later this should be specified as 1; otherwise it
399  should be 0 (default).
400 <tag><it>group</it>storeData</tag>
401  Specifies whether the records should be stored internally
402  in the Zebra system tables. If you want to maintain the raw records yourself,
403  this option should be false (0). If you want Zebra to take care of the records
404  for you, it should be true(1).
405 <tag>register</tag> 
406  Specifies the location of the various files that Zebra uses to represent
407  your system.
408 <tag>tempSetPath</tag>
409  Specifies the directory that the server uses for temporary result sets.
410  If not specified <tt>/tmp</tt> will be used.
411 <tag>profilePath</tag>
412  Specifies the location of profile specification paths.
413 <tag>attset</tag> 
414  Specifies the filename(s) of attribute set files for use in searching.
415 </descrip>
416
417 <sect1>Locating Records
418 <p>
419 The default behaviour of the Zebra system is to reference the
420 records from their original location, i.e. where they were found when you
421 ran <tt/zebraidx/.
422
423 If your records files are temporary - for example if you retrieve
424 them from the outside, or if they where temporarily mounted on a CD-ROM,
425 you may want Zebra to make a copy of them. To do this,
426 you specify 1 (true) in the <tt>storedata</tt> setting. When
427 the Z39.50 server retrieves records they will be read from the
428 internal file structures of the system.
429
430 <sect1>Indexing with no Record IDs (Simple Indexing)
431
432 <p>
433 If you have a set of records that you <em/never/ wish to delete
434 or modify you may find &dquot;indexing without records IDs&dquot; convenient.
435 This indexing method uses less space than the other methods and
436 is simple to use. 
437
438 To use this method, you simply don't provide the <tt>recordId</tt> entry
439 for the group of files that you index. To add a set of records you use
440 <tt>zebraidx</tt> with the <tt>update</tt> command. The
441 <tt>update</tt> command will always add all of the records to the index
442 becuase Zebra doesn't know how to match the new set of records with
443 existing records.
444
445 Consider a system in which you have a group of text files called
446 <tt>simple</tt>. That group of records should belong to a Z39.50 database
447 called <tt>textbase</tt>. The following <tt/zebra.cfg/ file will suffice:
448
449 <tscreen><verb>
450 profilePath: /usr/local/yaz
451 attset: bib1.att
452 attset: gils.att
453 simple.recordType: text
454 simple.database: textbase
455 </verb></tscreen>
456
457 Since the existing records in an index can not be addressed by their
458 IDs, it is impossible to delete records when using this method.
459
460 <sect1>Indexing with File Record IDs
461
462 <p>
463 If you have a set of external records that you wish to index you may
464 use the file key feature of the Zebra system. In short, the file key
465 feature mirrors a directory structure and its files efficiently. To
466 perform indexing of a directory with file keys, you specify the top-level
467 directory after the <tt>update</tt> command. The command will recursively
468 traverse the directories and compare each with whatever have been
469 indexed before in the same directory. If a file is new (not in
470 the previous version of the directory) it is inserted;
471 if a file was already indexed and it has been modified
472 since the last insertion the index is also modified; if a file is missing
473 since the last visit it is deleted from the index.
474
475 The resulting system is easy to administer. To delete a record
476 you simply have to delete the corresponding file (with <tt/rm/). 
477 To force update of a given file, you may use the <tt>touch</tt>
478 command. And to add files create new files (or directories with files).
479 For your changes to take effect you must run <tt>zebraidx</tt> with
480 the same directory root again.
481
482 To use this method, you must specify <tt>file</tt> as the value
483 of <tt>recordId</tt> in the configuration file. In the configuration
484 also set <tt>storeKeys</tt> to <tt>1</tt>, since the Zebra
485 indexer must save additional information per record in order to
486 modify/delete the records at a later time.
487
488 For example, to update group <tt>esdd</tt> records below
489 <tt>/home/grs</tt> you could type:
490 <tscreen><verb>
491 $ zebraidx -g esdd update /home/grs
492 </verb></tscreen>
493
494 The corresponding configuration file includes:
495 <tscreen><verb>
496 esdd.recordId: file
497 esdd.recordType: grs
498 esdd.storeKeys: 1
499 </verb></tscreen>
500
501 <em>Important note: You cannot start out with a group of records with simple
502 indexing (no record IDs as in the previous section) and then later
503 enable file record Ids. Zebra must know from the first time that you
504 index the group that
505 the files should be indexed with file record IDs.
506 </em>
507
508 You cannot explicitly delete records when using this method. Instead
509 you have to delete the files from the file system (or remove them)
510 and then run <tt>zebraidx</tt> with the <tt>update</tt> again.
511
512 <sect1>Indexing with General Record IDs
513 <p>
514 When using this method you specify an (almost) arbritrary record key
515 based on the contents of the record itself and other system
516 information. If you have a group of records that have an external
517 ID associated with each records, this method is convenient. For
518 example, the record may contain a title or a unique ID-number. In either
519 case you specify the Z39.50 attribute set and use-attribute location
520 in which this information is stored.
521
522 As before, the record ID is defined by the <tt>recordId</tt> setting
523 in the configuration file. The value of the record ID specification
524 consists of one or more tokens separated by whitespace. The resulting
525 ID is
526 represented in the index by concatenating the tokens and separating them by
527 ASCII value (1).
528
529 There are three kinds of tokens:
530 <descrip>
531 <tag>Internal record info</tag> The token refers to a key that is
532 extracted from the record. The syntax of this token is
533  <tt/(/ <em/set/ <tt/,/ <em/use/ <tt/)/, where <em/set/ is the
534 attribute set ordinal number and <em/use/ is the use value of the attribute.
535 <tag>System variable</tag> The system variables are preceded by
536 <verb>$</verb> and immediately followed by the system variable name, which
537 may one of
538  <descrip>
539  <tag>group</tag> Group name.
540  <tag>database</tag> Current database specified.
541  <tag>type</tag> Record type.
542  </descrip>
543 <tag>Constant string</tag> A string used as part of id &mdash; surrounded
544  by single- or double quotes.
545 </descrip>
546
547 The test GILS records that comes with the Zebra distribution contain a
548 unique ID
549 in the Control-Identifier field. This field is mapped to the Bib-1
550 use attribute 1007. To use this field as a record id, specify
551 <tt>(1,1007)</tt> as the value of the <tt>recordId</tt> in the
552 configuration file. If you have other record types that don't
553 contain an ID in the same field, you might add the record type
554 in the record id of the gils records as well, to prevent matches
555 of other types of records. In this case the recordId might be
556 set like this:
557 <tscreen><verb>
558 gils.recordId: $type (1,1007)
559 </verb></tscreen>
560
561 As for the file record id case described in the previous section
562 updating your system is simply a matter of running <tt>zebraidx</tt>
563 with the <tt>update</tt> command. However, the update with general
564 keys is considerably slower than with file record IDs, since all files
565 visited must be (re)read to find their IDs. 
566
567 You may have noticed that when using the general record IDs
568 method, you can only add or modify existing records with the <tt>update</tt>
569 command. If you wish to delete records, you must use another command,
570 <tt>delete</tt>, which a root directory as a parameter. This will remove
571 all records that match the files below the root directory.
572
573 <sect1>Register location
574
575 <p>
576 Normally, the index files that form dictionaries, inverted
577 files, record info, etc., are stored in the directory where you run
578 <tt>zebraidx</tt>. If you wish to store these, possibly large, files
579 somewhere else, you must add the <tt>register</tt> entry to the
580 configuration file. Furthermore, the Zebra system allows its file
581 structures to
582 span multiple file systems, which is useful if a very large number of
583 records are stored.
584
585 The value <tt>register</tt> of register is a sequence of tokens.
586 Each token takes the form:
587 <tscreen>
588 <em>dir</em><tt>:</tt><em>size</em>. 
589 </tscreen>
590 The <em>dir</em> specifies a directory in which index files will be
591 stored and the <em>size</em> specifies the maximum size of all
592 files in that directory. The Zebra indexer system fill each directory
593 in the order specified and use the next specified directories as needed.
594 The <em>size</em> is an integer followed by a qualifier
595 code, <tt>M</tt> for megabytes, <tt>k</tt> for kilobytes.
596
597 For instance, if you have two spare disks :) and the first disk is mounted
598 on <tt>/d1</tt> and has 200 Mb of free space and the
599 second, mounted on <tt>/d2</tt> has 300 Mb, you could
600 put this entry in your configuration file:
601 <tscreen><verb>
602 register: /d1:200M /d2:300M
603 </verb></tscreen>
604
605 <sect>The Z39.50 Server
606
607 <p>
608
609 <sect1>Running the server
610 <p>
611 The server <tt>zebrasrv</tt> supports the same set of options as the 
612 test server <tt>ztest</tt> that comes with YAZ. As for the 
613 <tt>zebraidx</tt> the option <tt>-c</tt> specifies the configuration
614 filename. When the Zebra server is executed with its normal log level it 
615 prints (not too detailed) information about the incoming queries. 
616 This is useful if you don't happen to know what attributes your client sends.
617
618 Note that the server doesn't support the static mode (-S). 
619
620 <sect>License
621
622 <p>
623 Copyright &copy; 1995, Index Data.
624
625 All rights reserved.
626
627 Use and redistribution in source or binary form, with or without
628 modification, of any or all of this software and documentation is
629 permitted, provided that the following conditions are met:
630
631 1. This copyright and permission notice appear with all copies of the
632 software and its documentation. Notices of copyright or attribution
633 which appear at the beginning of any file must remain unchanged.
634
635 2. The names of Index Data or the individual authors may not be used to
636 endorse or promote products derived from this software without specific
637 prior written permission.
638
639 3. Source code or binary versions of this software and its documentation
640 may be used in not-for-profit applications. For profit aplications -
641 including marketing a product based in whole or in part on this software,
642 or providing for-pay database services - must obtain a commercial
643 license from Index Data.
644
645 THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
646 EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
647 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
648 IN NO EVENT SHALL INDEX DATA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
649 INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
650 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR
651 NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
652 LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
653 OF THIS SOFTWARE.
654
655 <sect>About Index Data
656
657 <p>
658 Index Data is a consulting and software-development enterprise that
659 specialises in library and information management systems. Our
660 interests and expertise span a broad range of related fields, and one
661 of our primary, long-term objectives is the development of a powerful
662 information management
663 system with open network interfaces and hypermedia capabilities.
664
665 We make this software available free of charge for noncommercial
666 purposes, as a service to the networking community, and to further
667 the development of quality software for open network communication.
668
669 We'll be happy to answer questions about the software, and about ourselves
670 in general.
671
672 <tscreen>
673 Index Data&nl
674 Ryesgade 3&nl
675 DK-2200 K&oslash;benhavn N&nl
676 </tscreen>
677
678 <p>
679 <tscreen><verb>
680 Phone: +45 3536 3672
681 Fax  : +45 3536 0449
682 Email: info@index.ping.dk
683 </verb></tscreen>
684
685 The <it>Random House College Dictionary</it>, 1975 edition
686 offers this definition of the 
687 word &dquot;Zebra&dquot;:
688
689 <it>
690 Zebra, n., any of several horselike, African mammals of the genus Equus,
691 having a characteristic pattern of black or dark-brown stripes on
692 a whitish background.
693 </it>
694
695 </article>