Original 2.4
[marc4j.git] / src / org / marc4j / MarcXmlReader.java
1 // $Id: MarcXmlReader.java,v 1.4 2006/07/29 10:58:24 bpeters Exp $\r
2 /**\r
3  * Copyright (C) 2004 Bas Peters\r
4  *\r
5  * This file is part of MARC4J\r
6  *\r
7  * MARC4J is free software; you can redistribute it and/or\r
8  * modify it under the terms of the GNU Lesser General Public \r
9  * License as published by the Free Software Foundation; either \r
10  * version 2.1 of the License, or (at your option) any later version.\r
11  *\r
12  * MARC4J is distributed in the hope that it will be useful,\r
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
15  * Lesser General Public License for more details.\r
16  *\r
17  * You should have received a copy of the GNU Lesser General Public \r
18  * License along with MARC4J; if not, write to the Free Software\r
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
20  *\r
21  */\r
22 package org.marc4j;\r
23 \r
24 import java.io.InputStream;\r
25 \r
26 import javax.xml.transform.Source;\r
27 import javax.xml.transform.TransformerConfigurationException;\r
28 import javax.xml.transform.TransformerFactory;\r
29 import javax.xml.transform.sax.SAXTransformerFactory;\r
30 import javax.xml.transform.sax.TransformerHandler;\r
31 import javax.xml.transform.stream.StreamSource;\r
32 \r
33 import org.marc4j.marc.Record;\r
34 import org.xml.sax.InputSource;\r
35 \r
36 /**\r
37  * An iterator over a collection of MARC records in MARCXML format.\r
38  * <p>\r
39  * Basic usage:\r
40  * </p>\r
41  * \r
42  * <pre>\r
43  * InputStream input = new FileInputStream(&quot;file.xml&quot;);\r
44  * MarcReader reader = new MarcXmlReader(input);\r
45  * while (reader.hasNext()) {\r
46  *   Record record = reader.next();\r
47  *   // Process record\r
48  * }\r
49  * </pre>\r
50  * \r
51  * <p>Check the {@link org.marc4j.marc}&nbsp;package for examples about the use of \r
52  * the {@link org.marc4j.marc.Record}&nbsp;object model.</p>\r
53  *\r
54  * <p>\r
55  * You can also pre-process the source to create MARC XML from a different format\r
56  * using an XSLT stylesheet. The following example creates an iterator over a\r
57  * collection of MARC records in MARC XML format from a MODS source and outputs\r
58  * MARC records in MARC21 format:\r
59  * </p>\r
60  * \r
61  * <pre>\r
62  * InputStream in = new FileInputStream(&quot;modsfile.xml&quot;);\r
63  * \r
64  * MarcStreamWriter writer = new MarcStreamWriter(System.out, Constants.MARC8);\r
65  * MarcXmlReader reader = new MarcXmlReader(in, &quot;http://www.loc.gov/standards/marcxml/xslt/MODS2MARC21slim.xsl&quot;);\r
66  * while (reader.hasNext()) {\r
67  *   Record record = reader.next();\r
68  *   writer.write(record);\r
69  * }\r
70  * writer.close();\r
71  * </pre>\r
72  * \r
73  * @author Bas Peters\r
74  * @version $Revision: 1.4 $\r
75  *  \r
76  */\r
77 public class MarcXmlReader implements MarcReader {\r
78 \r
79   private RecordStack queue;\r
80 \r
81   /**\r
82    * Constructs an instance with the specified input stream.\r
83    * \r
84    * @param input\r
85    *          the input stream\r
86    */\r
87   public MarcXmlReader(InputStream input) {\r
88     this(new InputSource(input));\r
89   }\r
90 \r
91   /**\r
92    * Constructs an instance with the specified input source.\r
93    * \r
94    * @param input\r
95    *          the input source\r
96    */\r
97   public MarcXmlReader(InputSource input) {\r
98     this.queue = new RecordStack();\r
99     MarcXmlParserThread producer = new MarcXmlParserThread(queue, input);\r
100     producer.start();\r
101   }\r
102 \r
103   /**\r
104    * Constructs an instance with the specified input stream and stylesheet\r
105    * location.\r
106    * \r
107    * The stylesheet is used to transform the source file and should produce\r
108    * valid MARC XML records. The result is then used to create\r
109    * <code>Record</code> objects.\r
110    * \r
111    * @param input\r
112    *          the input stream\r
113    * @param stylesheetUrl\r
114    *          the stylesheet location\r
115    */\r
116   public MarcXmlReader(InputStream input, String stylesheetUrl) {\r
117         this(new InputSource(input), new StreamSource(stylesheetUrl));\r
118   }\r
119 \r
120   /**\r
121    * Constructs an instance with the specified input stream and stylesheet\r
122    * source.\r
123    * \r
124    * The stylesheet is used to transform the source file and should produce\r
125    * valid MARCXML records. The result is then used to create\r
126    * <code>Record</code> objects.\r
127    * \r
128    * @param input\r
129    *          the input stream\r
130    * @param stylesheet\r
131    *          the stylesheet source\r
132    */\r
133   public MarcXmlReader(InputStream input, Source stylesheet) {\r
134     this(new InputSource(input), stylesheet);\r
135   }\r
136   \r
137   /**\r
138    * Constructs an instance with the specified input source and stylesheet\r
139    * source.\r
140    * \r
141    * The stylesheet is used to transform the source file and should produce\r
142    * valid MARCXML records. The result is then used to create\r
143    * <code>Record</code> objects.\r
144    * \r
145    * @param input\r
146    *          the input source\r
147    * @param stylesheet\r
148    *          the stylesheet source\r
149    */\r
150   public MarcXmlReader(InputSource input, Source stylesheet) {\r
151     this.queue = new RecordStack();\r
152     MarcXmlParserThread producer = new MarcXmlParserThread(queue, input);\r
153     TransformerFactory factory = TransformerFactory.newInstance();\r
154     SAXTransformerFactory stf = (SAXTransformerFactory) factory;\r
155     TransformerHandler th = null;\r
156     try {\r
157       th = stf.newTransformerHandler(stylesheet);\r
158     } catch (TransformerConfigurationException e) {\r
159       throw new MarcException("Error creating TransformerHandler", e);\r
160     }\r
161     producer.setTransformerHandler(th);\r
162     producer.start();\r
163   }\r
164 \r
165   /**\r
166    * Constructs an instance with the specified input stream and transformer\r
167    * handler.\r
168    * \r
169    * The {@link javax.xml.transform.sax.TransformerHandler}&nbsp;is used to\r
170    * transform the source file and should produce valid MARCXML records. The\r
171    * result is then used to create <code>Record</code> objects. A\r
172    * <code>TransformerHandler</code> can be obtained from a\r
173    * <code>SAXTransformerFactory</code> with either a\r
174    * {@link javax.xml.transform.Source}&nbsp;or\r
175    * {@link javax.xml.transform.Templates}&nbsp;object.\r
176    * \r
177    * @param input\r
178    *          the input stream\r
179    * @param th\r
180    *          the transformation content handler\r
181    */\r
182   public MarcXmlReader(InputStream input, TransformerHandler th) {\r
183     this(new InputSource(input), th);\r
184   }\r
185 \r
186   /**\r
187    * Constructs an instance with the specified input source and transformer\r
188    * handler.\r
189    * \r
190    * The {@link javax.xml.transform.sax.TransformerHandler}&nbsp;is used to\r
191    * transform the source file and should produce valid MARCXML records. The\r
192    * result is then used to create <code>Record</code> objects. A\r
193    * <code>TransformerHandler</code> can be obtained from a\r
194    * <code>SAXTransformerFactory</code> with either a\r
195    * {@link javax.xml.transform.Source}&nbsp;or\r
196    * {@link javax.xml.transform.Templates}&nbsp;object.\r
197    * \r
198    * @param input\r
199    *          the input source\r
200    * @param th\r
201    *          the transformation content handler\r
202    */\r
203   public MarcXmlReader(InputSource input, TransformerHandler th) {\r
204     this.queue = new RecordStack();\r
205     MarcXmlParserThread producer = new MarcXmlParserThread(queue, input);\r
206     producer.setTransformerHandler(th);\r
207     producer.start();\r
208   }\r
209 \r
210   /**\r
211    * Returns true if the iteration has more records, false otherwise.\r
212    * \r
213    * @return boolean - true if the iteration has more records, false otherwise\r
214    */\r
215   public boolean hasNext() {\r
216     return queue.hasNext();\r
217   }\r
218 \r
219   /**\r
220    * Returns the next record in the iteration.\r
221    * \r
222    * @return Record - the record object\r
223    */\r
224   public Record next() {\r
225     return queue.pop();\r
226   }\r
227 \r
228 }