001 package com.javaworld.apr2000.sax;
002
003 /*
004 * Sample code by Mark Johnson, JavaWorld, April 2000.
005 * Code is may be used for any legal purpose, including commercial
006 * purposes, with no warranty expressed or implied.
007 * email: mark.johnson@javaworld.com
008 */
009 import org.xml.sax.*;
010 import java.lang.reflect.*;
011 import javax.xml.parsers.*;
012 import org.w3c.dom.*;
013 import org.xml.sax.SAXException;
014 import org.xml.sax.SAXParseException;
015 import java.util.*;
016 import java.io.*;
017
018 public class Lax extends org.xml.sax.HandlerBase {
019
020 // LAX translates XML content into method calls on this object
021 private Vector _vecHandlers = null;
022 private Vector _vecTags = null;
023 private static Class[] _caNoArgs = null;
024 private static Class[] _caAttrList = null;
025 private static Class[] _caString = null;
026 private SimpleErrorHandler _seh = new SimpleErrorHandler();
027
028 // Initialize class arrays used for reflection
029 static {
030 _caNoArgs = new Class[] {};
031 _caAttrList = new Class[] {org.xml.sax.AttributeList.class};
032 _caString = new Class[] {java.lang.String.class};
033 }
034 /**
035 * Lax default constructor
036 */
037 public Lax() {
038 super();
039 _vecHandlers = new Vector();
040 _vecTags = new Vector();
041 }
042 /**
043 * Lax ctor with a single handler
044 */
045 public Lax(Object handler_) {
046 super();
047 _vecHandlers = new Vector();
048 _vecTags = new Vector();
049 addHandler(handler_);
050 }
051 /**
052 * Add a handler to the list of handler objects.
053 * @param objHandler_ java.lang.Object
054 */
055 public void addHandler(Object objHandler_) {
056 _vecHandlers.addElement(objHandler_);
057 }
058 /**
059 * Handle an incoming block of text by calling the textOf method for the
060 * current tag.
061 */
062 public void characters(char[] caChars, int iStart, int iEnd) throws SAXException {
063 String sCurrentTag = sCurrentTag();
064
065 if (sCurrentTag != null) {
066 int i;
067 String sTextMethodName = "textOf" + sCurrentTag;
068 String sArg = null;
069
070 // Call every text method for current tag found in the list of handlers.
071 for (i = 0; i < _vecHandlers.size(); i++) {
072 Object oThisHandler = _vecHandlers.elementAt(i);
073 Method mTextMethod = mFindMethod(oThisHandler, sTextMethodName, _caString);
074 if (mTextMethod != null) {
075 try {
076 if (sArg == null) {
077 sArg = new String(caChars, iStart, iEnd);
078 }
079 mTextMethod.invoke(oThisHandler, new Object[] { sArg });
080 } catch (InvocationTargetException ex) {
081 System.err.println(ex);
082 } catch (IllegalAccessException ex) {
083 System.err.println(ex);
084 }
085 }
086 }
087 }
088 }
089 /**
090 * endDocument method comment.
091 */
092 public void endDocument() throws org.xml.sax.SAXException {
093 }
094 /**
095 * Call all end tag methods in the handler list
096 */
097 public void endElement(String sTag) throws SAXException {
098 int i;
099 String sEndMethodName = "end" + sTag;
100
101 // Call every tag start method for this tag found in the list of handlers.
102 for (i = 0; i < _vecHandlers.size(); i++) {
103 Object oThisHandler = _vecHandlers.elementAt(i);
104 Method mEndMethod = mFindMethod(oThisHandler, sEndMethodName, _caNoArgs);
105 if (mEndMethod != null) {
106 try {
107 mEndMethod.invoke(oThisHandler, new Object[] {});
108 } catch (InvocationTargetException ex) {
109 System.err.println(ex);
110 } catch (IllegalAccessException ex) {
111 System.err.println(ex);
112 }
113 }
114 }
115 popTag();
116 }
117 /**
118 * error method comment.
119 */
120 public void error(SAXParseException ex) throws SAXException {
121 _seh.error(ex);
122 }
123 /**
124 * fatalError method comment.
125 */
126 public void fatalError(SAXParseException ex) throws SAXException {
127 _seh.fatalError(ex);
128 }
129 /**
130 * Parse input XML with ShoppingListWriter
131 * @param args java.lang.String[]
132 */
133 public static void main(String args[]) {
134 if (args.length < 1) {
135 System.err.println("Usage: lax inputFile.xml [parserClass]");
136 System.exit(1);
137 }
138
139 String sInputFile = args[0];
140 String sRecipeFile;
141 String sShoppingListFile;
142 String sBase = sInputFile;
143
144 if (sBase.length() > 4 && sBase.toLowerCase().endsWith(".xml")) {
145 sBase = sBase.substring(0, sBase.length() - 4);
146 } else {
147 sInputFile = sBase + ".xml";
148 }
149 sRecipeFile = sBase + "-recipe.html";
150 sShoppingListFile = sBase + "-list.html";
151
152 Lax lax = new Lax();
153
154 ShoppingListWriter slw = new ShoppingListWriter(sShoppingListFile);
155 lax.addHandler(slw);
156
157 RecipeWriter rw = new RecipeWriter(sRecipeFile);
158 lax.addHandler(rw);
159
160 lax.parseDocument(true, lax, sInputFile);
161
162
163 }
164 /**
165 * Return a method of object oHandler
166 * with the given name and argument list, or null if not found
167 * @return java.lang.reflect.Method
168 * @param oHandler java.lang.Object - The handler object to search for a method.
169 * @param sTag java.lang.String - The tag to find.
170 */
171 private Method mFindMethod(Object oHandler, String sMethodName, Class[] caArgs) {
172 Method m = null;
173 Class classOfHandler = oHandler.getClass();
174
175 // Find a method with the given name and argument list
176 try {
177 m = classOfHandler.getMethod(sMethodName, caArgs);
178 } catch (NoSuchMethodException ex) {
179 // Ignore exception - no such method exists.
180 }
181 return m;
182 }
183 /**
184 * Reimplement this method to use a parser from a different vendor. See your
185 * parser package documentation for details.
186 * @param isValidating boolean
187 * @param documentHandler org.xml.sax.DocumentHandler
188 * @param errorHandler org.xml.sax.ErrorHandler
189 * @param sFilename java.lang.String
190 */
191 protected void parseDocument(boolean isValidating, HandlerBase handler, String sFilename) {
192 try {
193 // Get a "parser factory", an an object that creates parsers
194 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
195
196 // Set up the factory to create the appropriate type of parser
197 saxParserFactory.setValidating(isValidating);
198 saxParserFactory.setNamespaceAware(false); // Not this month...
199
200 SAXParser parser = saxParserFactory.newSAXParser();
201
202 parser.parse(new File(sFilename), handler);
203 } catch (Exception ex) {
204 System.err.println("Exception: " + ex);
205 System.exit(2);
206 }
207 }
208 /**
209 * Pop tag off of tag stack.
210 */
211 private void popTag() {
212 _vecTags.removeElementAt(_vecTags.size() - 1);
213 }
214 /**
215 * Push tag onto tag stack.
216 * @param sTag java.lang.String
217 */
218 private void pushTag(String sTag) {
219 _vecTags.addElement(sTag);
220 }
221 /**
222 * Return tag at top of tag stack. At any particular point in the parse,
223 * this string represents the tag being processed.
224 * @return java.lang.String
225 */
226 private String sCurrentTag() {
227 int iIndex = _vecTags.size() - 1;
228 if (iIndex >= 0) {
229 return (String)(_vecTags.elementAt(_vecTags.size() - 1));
230 } else {
231 return null;
232 }
233 }
234 /**
235 * startDocument method comment.
236 */
237 public void startDocument() throws org.xml.sax.SAXException {
238 }
239 /**
240 * Call all start methods for this tag.
241 */
242 public void startElement(String sTag, AttributeList alAttrs) {
243 int i;
244 String sStartMethodName = "start" + sTag;
245
246 pushTag(sTag);
247
248 // Call every tag start method for this tag found in the list of handlers.
249 for (i = 0; i < _vecHandlers.size(); i++) {
250 Object oThisHandler = _vecHandlers.elementAt(i);
251 Method mStartMethod = mFindMethod(oThisHandler, sStartMethodName, _caAttrList);
252 if (mStartMethod == null) {
253 mStartMethod = mFindMethod(oThisHandler, sStartMethodName, _caNoArgs);
254 }
255 if (mStartMethod != null) {
256 try {
257 // Call start method with or without attribute list
258 Class[] caMethodArgs = mStartMethod.getParameterTypes();
259 if (caMethodArgs.length == 0) {
260 mStartMethod.invoke(oThisHandler, new Object[] {});
261 } else {
262 mStartMethod.invoke(oThisHandler, new Object[] {alAttrs});
263 }
264 } catch (InvocationTargetException ex) {
265 System.err.println(ex);
266 } catch (IllegalAccessException ex) {
267 System.err.println(ex);
268 }
269 }
270 }
271 }
272 /**
273 * warning method comment.
274 */
275 public void warning(SAXParseException ex) throws SAXException {
276 _seh.warning(ex);
277 }
278 }