1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
|
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html SYSTEM "../../../dtd/strict.dtd">
<html>
<head>
<title>MARC4J</title>
<style>h1 {font-size: 16pt; font-family: Helvetica, Arial, san-serif }
h2 {font-size: 14pt; font-family: Helvetica, Arial, san-serif }</style>
</head>
<body>
<h1>Contents</h1>
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#download">Download</a></li>
<li><a href="#installing">Installing MARC4J</a></li>
<li><a href="#example">A first example</a></li>
<li><a href="#marcxml">Converting between MARC and MARCXML</a>
<ul>
<li><a href="#commandline">Command-line utilities</a></li>
<li><a href="#converter">The Converter class</a></li>
<li><a href="#marctomarcxml">Converting MARC to MARCXML</a></li>
<li><a href="#postprocess">Postprocessing MARCXML using XSLT</a></li>
<li><a href="#marcxmltomarc">Converting MARCXML to MARC</a></li>
<li><a href="#preprocess">Preprocessing MARCXML using XSLT</a></li>
<li><a href="#xmlschema">Validating against a W3C XML Schema</a></li>
<li><a href="#relaxng">Validating against a RELAX NG schema</a></li>
</ul>
</li>
<li><a href="#charconv">Character conversions</a></li>
<li><a href="#object">Using the record object model</a></li>
</ul>
<h1><a name="intro">Introduction</a></h1>
<p>This document provides basic examples that illustrate the features provided by the MARC4J library and demonstrates how they can be used. For additional information check the Javadoc <a href="apidoc/index.html">documentation</a>.</p>
<p>MARC4J is an easy to use library for working with <a href="http://lcweb.loc.gov/marc/">MARC</a> records in Java. The library consists of an event-based MARC parser, an object model for in-memory editing of MARC record objects and SAX2 based producers and consumers for conversions between MARC and <a href="http://www.loc.gov/standards/marcxml/">MARCXML</a>, the new XML exchange format for MARC as published by the Library of Congress. For preprocessing XML to create MARCXML, or for postprocessing MARCXML to create a different format, XSLT support is added through JAXP. JAXP is a vendor-neutral interface for working with XML in Java. This means that you can use any XML parser or XSLT processor that is JAXP compliant.</p>
<h1><a name="download">Download</a></h1>
<p>MARC4J can be downloaded from <a href="http://marc4j.tigris.org">http://marc4j.tigris.org</a>, the project home for MARC4J.</p>
<h1><a name="installing">Installing MARC4J</a></h1>
<p>MARC4J requires no additional libraries. Simply make sure that your Java environment is able to locate the library, for example by adding the <code>marc4j.jar</code> to your Java classpath environment variable.</p>
<p>If you plan to use the XML features that MARC4J offers, a SAX2 parser is needed with optionally a JAXP compatible XSLT processor to add XSLT support. Examples of SAX2 parsers are <a href="http://www.gnu.org/software/classpathx/jaxp/">GNU JAXP</a>, <a href="http://xml.apache.org/xerces2-j/index.html">Xerces</a>, <a href="http://xml.apache.org/crimson/index.html">Crimson</a> and <a href="http://piccolo.sourceforge.net/">Piccolo</a>. Examples of JAXP compatible XSLT engines are <a href="http://saxon.sourceforge.net/">Saxon</a> and <a href="http://xml.apache.org/xalan-j/index.html">Xalan</a>.</p>
<p>If you need W3C XML Schema support consider using Xerces 2. Also Sun's <a href="http://java.sun.com/xml/jaxp/">Java API for XML Processing</a> (JAXP) v1.2 provides all the necessary libraries to use MARC4J with XML.</p>
<h1><a name="example">A first example</a></h1>
<p>Using MARC4J one can write Java applications that involve MARC records simply by implementing the <a href="apidoc/org/marc4j/MarcHandler.html">MarcHandler</a> and optionally the <a href="apidoc/org/marc4j/ErrorHandler.html">ErrorHandler</a> interface. It is also possible to extend the <a <a href="apidoc/org/marc4j/helpers/DefaultHandler.html">DefaultHandler</a>, a class that implements all the methods in MarcHandler and ErrorHandler.</p>
<p>The <code>MarcHandler</code> interface provides methods that receive MARC parser events (such as the start and the end of a record) from the MARC parser. The interface defines the following methods:</p>
<pre>
public void startCollection();
public void startRecord(Leader leader);
public void controlField(String tag, char[] data);
public void startDataField(String tag, char ind1, char ind2);
public void subfield(char code, char[] data);
public void endDataField(String tag);
public void endRecord();
public void endCollection();</pre>
<p>The following <a name="taggedwriter">code sample</a> shows a basic <code>MarcHandler</code> that writes MARC records in tagged display format. This example implements all methods in the <code>MarcHandler</code> interface.</p>
<pre>
import java.io.*;
import org.marc4j.*;
import org.marc4j.marc.Leader;
import org.marc4j.helpers.ErrorHandlerImpl;
public class TaggedWriter implements MarcHandler {
/** The Writer object */
private Writer out;
/** Set the writer object */
public void setWriter(Writer out) {
this.out = out;
}
public void startCollection() {
if (out == null)
System.exit(0);
}
public void startRecord(Leader leader) {
rawWrite("Leader ");
rawWrite(leader.marshal());
rawWrite('\n');
}
public void controlField(String tag, char[] data) {
rawWrite(tag);
rawWrite(' ');
rawWrite(new String(data));
rawWrite('\n');
}
public void startDataField(String tag, char ind1, char ind2) {
rawWrite(tag);
rawWrite(' ');
rawWrite(ind1);
rawWrite(ind2);
}
public void subfield(char code, char[] data) {
rawWrite('$');
rawWrite(code);
rawWrite(new String(data));
}
public void endDataField(String tag) {
rawWrite('\n');
}
public void endRecord() {
rawWrite('\n');
}
public void endCollection() {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void rawWrite(char c) {
try {
out.write(c);
} catch (IOException e) {
e.printStackTrace();
}
}
private void rawWrite(String s) {
try {
out.write(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}</pre>
<p>Add the following driver class to complete the program. This driver demonstrates how to register the <code>MarcHandler</code> implementation and send the input file to the parser:</p>
<pre>
class Driver {
public static void main(String args[]) {
try {
MarcReader reader = new MarcReader();
TaggedWriter handler = new TaggedWriter();
Writer out = new BufferedWriter(new OutputStreamWriter(System.out));
handler.setWriter(out);
reader.setMarcHandler(handler);
// reader.setErrorHandler(new ErrorHandlerImpl());
reader.parse(args[0]);
} catch (IOException e) {
e.printStackTrace();
}
}
}</pre>
<p>To be able to report parser errors we have to register an <code>ErrorHandler</code> implementation. The error handler is optional, but it is highly recommended to use this feature. To add the implementation provided by MARC4J do the following:</p>
<pre>reader.setErrorHandler(new ErrorHandlerImpl());</pre>
<p>Of course it is also possible to create a different error handler by implementing the ErroHandler interface:</p>
<pre>
public abstract void warning(MarcReaderException exception);
public abstract void error(MarcReaderException exception);
public abstract void fatalError(MarcReaderException exception);</pre>
<p>Basically this is what MARC4J is about. The MarcReader takes care of reading MARC records and writing a program is simply a matter of implementing the two interfaces.</p>
<h1><a name="marcxml">Converting between MARC and MARCXML</a></h1>
<p>Besides working with MARC records in tape format, MARC4J also provides SAX2 producers and consumers for working with MARCXML documents. MARCXML is a simple format to represent a MARC record in XML. It is part of a larger <a href="http://www.loc.gov/standards/marcxml//marcxml-architecture.html">framework</a> developed by the Library of Congress. Click <a href="http://www.loc.gov/standards/marcxml//Sandburg/sandburg.xml">here</a> to see what a MARCXML document looks like.</p>
<h2><a name="commandline">Command-line utilities</a></h2>
<p>MARC4J provides a command-line utility to convert records in MARC tape format to MARCXML and back. To convert MARC to MARCXML use the following command from the command-line:</p>
<pre>java org.marc4j.util.MarcXmlWriter <input-file></pre>
<p>Run the program with the following command for help:</p>
<pre>java org.marc4j.util.MarcXmlWriter -usage</pre>
<p>It is also possible to postprocess the MARCXML result using XSLT. The following command converts the MARC input file to MODS, a MARC based metadata format:</p>
<pre>java org.marc4j.util.MarcXmlWriter -xsl <a href="http://www.loc.gov/standards/marcxml//xslt/MARC21slim2MODS.xsl">MARC21slim2MODS.xsl</a> <input-file></pre>
<p>To convert MARCXML back to MARC tape format use the following command from the command-line:</p>
<pre>java org.marc4j.util.XmlMarcWriter <input-file></pre>
<p>Run the program with the following command for help:</p>
<pre>java org.marc4j.util.XmlMarcWriter -usage</pre>
<p>It is also possible to use XSLT to preprocess a document, for example to transform OAI MARC XML to MARCXML, before the input is converted to MARC tape format.</p>
<h2><a name="converter">The Converter class</a></h2>
<p>The conversion between MARC and MARCXML is provided through the <a href="apidoc/org/marc4j/marcxml/Converter.html">Converter</a> class. This class is similar to the <code>javax.xml.transform.Transformer</code> class in JAXP. You can even use the same <code>javax.xml.transform.Source</code> and <code>javax.xml.transform.Result</code> implementations. For MARC support MARC4J provides a <a href="apidoc/org/marc4j/marcxml/MarcSource.html">MarcSource</a> and a <a href="apidoc/org/marc4j/marcxml/MarcResult.html">MarcResult</a> class. <code>MarcSource</code> and <code>MarcResult</code> are modelled after the <code>javax.xml.transform.SAXSource</code> and <code>javax.xml.transform.SAXResult</code> classes. A <code>MarcSource</code> takes a <code>org.marc4j.MarcReader</code> object and an input source as parameters and the MarcResult takes a <code>MarcHandler</code> as parameter.</p>
<p>The following code sample performs the same task as the <a href="#taggedwriter">first example</a>, now using the <code>Converter</code> class:</p>
<pre>
class Driver {
public static void main(String args[]) {
if(args.length < 1) {
System.out.println("Driver <input-file>");
return;
}
String input = args[0];
try {
MarcReader reader = new MarcReader();
TaggedWriter handler = new TaggedWriter();
Writer out = new BufferedWriter(new OutputStreamWriter(System.out));
MarcSource source = new MarcSource(reader, input);
MarcResult result = new MarcResult();
result.setHandler(handler);
Converter converter = new Converter();
converter.convert(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
}</pre>
<h2><a name="marctomarcxml">Converting MARC to MARCXML</a></h2>
<p>To convert MARC to MARCXML use <a href="apidoc/org/marc4j/marcxml/MarcXmlReader.html">MarcXmlReader</a>. This class is a subclass of <code>org.sax.xml.helpers.XmlFilterImpl</code> and produces SAX2 events that can be delivered to an XSLT processor or to another program that consumes SAX2 events. To output XML you can use a null-transform, or use an XMLWriter program. The following code sample shows the basic use of the <code>org.marc4j.marcxml.MarcXmlReader</code>:</p>
<pre>
class Driver {
public static void main(String args[]) {
if(args.length < 1) {
System.out.println("Driver <input-file>");
return;
}
String input = args[0];
try {
MarcXmlReader producer = new MarcXmlReader();
InputSource in = new InputSource(new InputStreamReader(new FileInputStream(input)));
Source source = new SAXSource(producer, in);
Writer writer = new BufferedWriter(new OutputStreamWriter(System.out));
Result result = new StreamResult(writer);
Converter converter = new Converter();
converter.convert(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
}</pre>
<p>This sample perfoms a null transform, which means that it will output well-formed XML. </p>
<h2><a name="postprocess">Postprocessing MARCXML using XSLT</a></h2>
<p>Provide an XSLT stylesheet to postprocess the SAX2 events with XSLT:</p>
<pre>
class Driver {
public static void main(String args[]) {
if(args.length < 1) {
System.out.println("Driver <input-file> [<stylesheet>]");
return;
}
String input = args[0];
String stylesheet = (args.length > 1) ? args[1] : null;
try {
MarcXmlReader producer = new MarcXmlReader();
InputSource in = new InputSource(new InputStreamReader(new FileInputStream(input)));
Source source = new SAXSource(producer, in);
Writer writer = new BufferedWriter(new OutputStreamWriter(System.out));
Result result = new StreamResult(writer);
Converter converter = new Converter();
if (stylesheet != null) {
Source style = new StreamSource(new File(stylesheet).toURL().toString());
converter.convert(style, source, result);
} else {
converter.convert(source, result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}</pre>
<h2><a name="marcxmltomarc">Converting MARCXML to MARC</a></h2>
<p>To convert MARCXML back to MARC tape format the <a href="apidoc/org/marc4j/util/MarcWriter.html">MarcWriter</a> can be used to consume the <code>org.marc4j.MarcHandler</code> events produced by the <a href="apidoc/org/marc4j/marcxml/MarcXmlHandler.html">MarcXmlHandler</a>, a SAX2 content handler that can be used with any SAX2 compliant XML parser. <code>MarcXmlHandler</code> reports events to the <code>MarcHandler</code>, just like <code>MarcReader</code>. This means that you can use the same <code>MarcHandler</code> implementations. The following code sample uses a <code>SAXSource</code> and a <code>MarcResult</code> to convert MARCXML records to MARC tape format:</p>
<pre>
class Driver {
public static void main(String args[]) {
if(args.length < 1) {
System.out.println("Driver <input-file>");
return;
}
String input = args[0];
try {
Writer writer = new BufferedWriter(new OutputStreamWriter(System.out));
MarcWriter handler = new MarcWriter(writer);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setErrorHandler(new SaxErrorHandler());
InputSource in = new InputSource(new File(input).toURL().toString());
Source source = new SAXSource(xmlReader, in);
Result result = new MarcResult(handler);
Converter converter = new Converter();
converter.convert(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
}</pre>
<h2><a name="preprocess">Preprocessing MARCXML using XSLT</a></h2>
<p>To preprocess the input XML using an XSLT stylesheet that outputs MARCXML, provide a stylesheet:</p>
<pre>
class Driver {
public static void main(String args[]) {
if(args.length < 1) {
System.out.println("Driver <input-file> [<stylesheet>]");
return;
}
String input = args[0];
String stylesheet = (args.length > 1) ? args[1] : null;
try {
Writer writer = new BufferedWriter(new OutputStreamWriter(System.out));
MarcWriter handler = new MarcWriter(writer);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setErrorHandler(new SaxErrorHandler());
InputSource in = new InputSource(new File(input).toURL().toString());
Source source = new SAXSource(xmlReader, in);
Result result = new MarcResult(handler);
Converter converter = new Converter();
if (stylesheet != null) {
Source style = new StreamSource(new File(stylesheet).toURL().toString());
converter.convert(style, source, result);
} else {
converter.convert(source, result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}</pre>
<p>It is also possible to perform XML transformations without converting the result to MARC tape format using the <code>Converter</code> class, since it uses the <code>Transformer</code> class, but of course you can also directly use the <code>Transformer</code> class. It should even be possible to provide a <code>SAXSource</code> and collect the result in a <code>javax.xml.transform.dom.DOMResult</code>.</p>
<h2><a name="xmlschema">Validating against a W3C XML Schema</a></h2>
<p>Since <code>MarcXmlHandler</code> is a standard SAX2 content handler, you can use standard SAX2 features like for example XML validation. Validating the MARCXML document against the W3C XML Schema for MARCXML as provided by the Library of Congress can be done as follows:</p>
<pre>
public class Driver {
public static void main(String args[]) throws Exception {
if(args.length < 1) {
System.out.println("Driver <input-file>");
return;
}
try {
Writer writer = new BufferedWriter(new OutputStreamWriter(System.out));
MarcWriter handler = new MarcWriter(writer);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
SAXParser saxParser = factory.newSAXParser();
saxParser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
saxParser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource",
new File("<a href="http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">MARC21slim.xsd</a>"));
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setErrorHandler(new SaxErrorHandler());
InputSource in = new InputSource(new File(input).toURL().toString());
Source source = new SAXSource(xmlReader, in);
Result result = new MarcResult(handler);
Converter converter = new Converter();
converter.convert(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
</pre>
<h2><a name="relaxng">Validating against a RELAX NG schema</a></h2>
<p>The following driver class validates a MARCXML document against a RELAX NG schema using Sun's Multi Schema validator (<a href="http://wwws.sun.com/software/xml/developers/multischema/">MSV</a>). The example uses the JAXP implementation provided by the MSV validator. The program outputs MARC ISO-2709 records.</p>
<pre>
public class Driver {
public static void main(String args[]) throws Exception {
if(args.length < 1) {
System.out.println("Driver <input-file>");
return;
}
try {
Writer writer = new BufferedWriter(new OutputStreamWriter(System.out));
MarcWriter handler = new MarcWriter(writer);
SAXParserFactory factory = new com.sun.msv.verifier.jaxp.SAXParserFactoryImpl();
factory.setNamespaceAware(true);
SAXParser saxParser = factory.newSAXParser();
saxParser.setProperty("http://www.sun.com/xml/msv/schema",
new File("<a href="http://marc4j.tigris.org/files/documents/220/687/MARC21slim.rng">MARC21slim.rng</a>"));
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setErrorHandler(new SaxErrorHandler());
InputSource in = new InputSource(new File(args[0]).toURL().toString());
Source source = new SAXSource(xmlReader, in);
Result result = new MarcResult(handler);
Converter converter = new Converter();
converter.convert(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
</pre>
<h1><a name="charconv">Character conversions</a></h1>
<p>MARC4J provides full support for character conversions between MARC-8 (ANSEL) and UCS/Unicode. Converting a character array or string is simple. Both the convert method of <a href="apidoc/org/marc4j/util/AnselToUnicode.html">AnselToUnicode</a> and <a href="apidoc/org/marc4j/util/UnicodeToAnsel.html">UnicodeToAnsel</a> take a character array or string as parameter.</p>
<p>The following code sample implements the subfield method in the <code>MarcHandler</code> interface and converts MARC-8 to UCS/Unicode:</p>
<pre>
public void subfield(char code, char[] data) {
rawWrite('$');
rawWrite(code);
char[] ch = AnselToUnicode.convert(data)
rawWrite(new String(ch)));
}</pre>
<p>Besides conversions between MARC-8 and UCS/Unicode, MARC4J also provides character conversions between UCS/Unicode and ISO-5426 (<a href="apidoc/org/marc4j/util/Iso5426ToUnicode.html">Iso5426ToUnicode</a> and <a href="apidoc/org/marc4j/util/UnicodeToIso5426.html">UnicodeToIso5426</a>) and ISO-6937 (<a href="apidoc/org/marc4j/util/Iso6937ToUnicode.html">Iso6937ToUnicode</a> and <a href="apidoc/org/marc4j/util/UnicodeToIso6937.html">UnicodeToIso6937</a>).</p>
<h1><a name="object">Using the record object model</a></h1>
<p>The record object model can be used to edit MARC records as objects and to marshal record objects to MARC tape format. The following code sample implements the <code>MarcHandler</code> to build Record objects and marshal the objects to MARC tape format using the <code>marshal()</code> method in the <a href="apidoc/org/marc4j/marc/Record.html">Record</a> class:</p>
<pre>
public void startCollection() {
if (out == null)
System.exit(0);
}
public void startRecord(Leader leader) {
this.record = new Record();
record.add(leader);
}
public void controlField(String tag, char[] data) {
record.add(new ControlField(tag, data));
}
public void startDataField(String tag, char ind1, char ind2) {
datafield = new DataField(tag, ind1, ind2);
}
public void subfield(char code, char[] data) {
if (convert)
try {
datafield.add(new Subfield(code,
UnicodeToAnsel.convert(data)));
} catch (IOException e) {
e.printStackTrace();
}
else
datafield.add(new Subfield(code, data));
}
public void endDataField(String tag) {
record.add(datafield);
}
public void endRecord() {
try {
rawWrite(record.marshal());
} catch (IOException e) {
e.printStackTrace();
} catch (MarcException e) {
e.printStackTrace();
}
}
public void endCollection() {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void rawWrite(String s)
throws IOException {
out.write(s);
}
</pre>
<p>If you want to work with Record objects in your program, consider using the <a href="apidoc/org/marc4j/helpers/RecordBuilder.html">RecordBuilder</a> together with a <a href="apidoc/org/marc4j/helpers/RecordHandler.html">RecordHandler</a> implementation. The <code>RecordBuilder</code> creates MARC record objects and reports them to the <code>RecordHandler</code> interface. By using the record handler it is possible to handle large records sets. If you need access to a collection of record objects you can use the <a href="apidoc/org/marc4j/marc/Collection.html">Collection</a> class which serves as a container for a collection of record objects.</p>
<p>Copyright © 2002-2003 <a href="mailto:mail@bpeters.com">Bas Peters</a>. All Rights Reserved.</p>
<p>Last updated: $Date: 2003/04/11 20:26:02 $</p>
<!-- $Id: index.html,v 1.9 2003/04/11 20:26:02 bpeters Exp $ -->
</body>
</html>
|