1 package hotsax.html.sax;
2
3 import org.xml.sax.*;
4 import org.xml.sax.helpers.*;
5 import org.xml.sax.ext.*;
6
7 import java.io.*;
8 import java.util.*;
9
10
11
12 /***
13 * SaxHandlerDelegate - provides a clean interface between the
14 * Byacc/J generated HtmlParse and the SaxParser.
15 */
16
17 public class DebugParserDelegate implements ParserDelegate {
18
19 private HtmlParser parser = null;
20 private XMLReader reader = null;
21 private ContentHandler contentHandler = null;
22 private LexicalHandler lexicalHandler = null;
23
24 private org.xml.sax.helpers.AttributesImpl attrList;
25
26
27 public DebugParserDelegate(HtmlParser HtmlParser) {
28 this.parser = parser;
29 attrList = new org.xml.sax.helpers.AttributesImpl();
30 }
31
32
33
34
35
36 /***
37 * Parse a startDocument event and pass it to the resigtered content handler.
38 * This method fires in response to a HtmlParser.EOF lexer token beging recognised.
39 * SOF is a virtual token fired as the first event after the file is opened.
40 */
41 public void startDocument()
42 {
43 try {
44 if (contentHandler != null)
45 contentHandler.startDocument();
46
47 System.out.println("Debug: document started");
48 }
49 catch (SAXException ex)
50 {
51 parser.yyerror(ex.getMessage());
52 }
53 }
54
55
56 /***
57 * Parse a PI and pass it to the contentHandler event
58 * (does not pass xml declaration: <?xml version = 1>)
59 * Separates the target from the data by using whitespace.
60 *
61 */
62 public void processingInstruction(HtmlParserVal target, HtmlParserVal lval)
63 {
64 try {
65 if (contentHandler != null) {
66 StringTokenizer stok = new StringTokenizer(lval.sval);
67
68 if (stok.hasMoreElements())
69 {
70 String data;
71 if (stok.hasMoreElements())
72 data = stok.nextToken();
73 else
74 data = "";
75 if (!target.equals("xml"))
76 contentHandler.processingInstruction(target.toString(), data);
77 }
78 }
79 }
80 catch (SAXException ex)
81 {
82 parser.yyerror(ex.getMessage());
83 }
84 }
85
86 /***
87 * Initialize the start of a start element. Prepares the attribute list
88 * to collect any attributes.
89 */
90 public void startElement()
91 {
92 attrList.clear();
93 }
94
95 /***
96 * Adds an attribute to the list. The name of the attribute is normalized
97 * to lowercase
98 */
99 public void addAttribute(String name, String value) {
100 attrList.addAttribute("", "", name, "NMTOKEN", value);
101 System.out.println("attribute added " + name + " = \"" + value + "\"");
102 }
103
104 public HtmlParserVal getAttributes() {
105 HtmlParserVal aList = new HtmlParserVal(attrList);
106 return aList;
107 }
108
109 public void startElement(HtmlParserVal lval, HtmlParserVal attrList) {
110 try {
111 if (contentHandler != null)
112 {
113 contentHandler.startElement("", lval.sval, "", (Attributes)attrList.obj);
114 }
115 }
116 catch (SAXException ex)
117 {
118 parser.yyerror(ex.getMessage());
119 }
120 }
121
122 /***
123 * Fire startElement event. Note handled the actual beginning of the element by now
124 * and have collected all attributes (if any)
125 */
126 public void startElement(HtmlParserVal lval) {
127 try {
128 if (contentHandler != null)
129 {
130 contentHandler.startElement("", lval.sval, "", attrList);
131 }
132 }
133 catch (SAXException ex)
134 {
135 parser.yyerror(ex.getMessage());
136 }
137 }
138
139
140 /***
141 * collect characters from parse stream. Unwrap the HtmlParserVal.sval
142 * String to a character array.
143 * TODO: After creating a LexicalHandler, make sure this gets called
144 * in the comment state.
145 * TODO: This might be better done in the collection process
146 * rather than always using a String. I.e. getting a bunch of chars instead of
147 * incrementally appending one char at a time from yytext()
148 */
149 public void characters(HtmlParserVal lval)
150 {
151 try {
152 if (contentHandler != null)
153 {
154 char ch[] = lval.sval.toCharArray();
155 contentHandler.characters(ch, 0, lval.sval.length());
156 }
157 }
158 catch (SAXException ex)
159 {
160 parser.yyerror(ex.getMessage());
161 }
162 }
163
164
165 /***
166 * Fire endElement event. The name of the element is passed to the event handler.
167 * Note these might be optionally missing in the HTML case.
168 */
169 public void endElement(HtmlParserVal lval)
170 {
171 try {
172 if (contentHandler != null)
173 contentHandler.endElement("", lval.sval, "");
174 }
175 catch (SAXException ex)
176 {
177 parser.yyerror(ex.getMessage());
178 }
179 }
180
181 /***
182 * Fire endDocument event.
183 */
184 public void endDocument()
185 {
186 try {
187 if (contentHandler != null)
188 contentHandler.endDocument();
189 }
190 catch (SAXException ex)
191 {
192 parser.yyerror(ex.getMessage());
193 }
194 }
195
196
197
198 /***
199 * comment handler
200 * Note, these are delegate to the XMLReader's LexicalHandler if any
201 * TODO: Check the property of the reader for its existance.
202 */
203 public void comment(HtmlParserVal lval) {
204 try {
205 if (lexicalHandler != null)
206 {
207 char ch[] = lval.sval.toCharArray();
208 lexicalHandler.comment(ch, 0, lval.sval.length());
209 }
210 }
211 catch (SAXException ex)
212 {
213 parser.yyerror(ex.getMessage());
214 }
215 }
216
217
218 /***
219 * CDATA handler
220 * Note, these are delegate to the XMLReader's LexicalHandler if any
221 * This only marks the start boundary condition. Text still goes through characters()
222 */
223 public void startCDATA() {
224 try {
225 if (lexicalHandler != null)
226 {
227 lexicalHandler.startCDATA();
228 }
229 }
230 catch (SAXException ex)
231 {
232 parser.yyerror(ex.getMessage());
233 }
234 }
235
236 /***
237 * CDATA handler
238 * Note, these are delegate to the XMLReader's LexicalHandler if any
239 * This only marks the end boundary of the CDATA section. Text still goes through characters()
240 */
241 public void endCDATA() {
242 try {
243 if (lexicalHandler != null)
244 {
245 lexicalHandler.endCDATA();
246 }
247 }
248 catch (SAXException ex)
249 {
250 parser.yyerror(ex.getMessage());
251 }
252 }
253
254 /***
255 * Start the beginning of the DOCTYPE (DTD) declaration
256 * Note, these are delegate to the XMLReader's LexicalHandler if any
257 */
258 public void startDTD(HtmlParserVal lval) {
259 try {
260 if (lexicalHandler != null)
261 {
262 StringTokenizer stok = new StringTokenizer(lval.sval);
263
264 if (stok.hasMoreElements())
265 {
266 String target = stok.nextToken();
267 String data;
268 if (stok.hasMoreElements())
269 data = stok.nextToken();
270 else
271 data = "";
272
273 lexicalHandler.startDTD(target, data, null);
274 }
275 }
276 }
277 catch (SAXException ex)
278 {
279 parser.yyerror(ex.getMessage());
280 }
281 }
282
283 /***
284 * End the DOCTYPE declaration
285 */
286 public void endDTD() {
287 try {
288 if (lexicalHandler != null)
289 lexicalHandler.endDTD();
290 }
291 catch (SAXException ex)
292 {
293 parser.yyerror(ex.getMessage());
294 }
295 }
296
297
298
299
300
301 /***
302 * used by the SaxParser to set itself in ParserDelegate
303 */
304 public void setXMLReader(XMLReader reader) {
305 this.reader = reader;
306
307 try {
308 if (reader != null)
309 {
310 contentHandler = reader.getContentHandler();
311 lexicalHandler = (LexicalHandler)reader.getProperty("http://xml.org/sax/properties/lexical-handler");
312 }
313 }
314 catch (SAXNotRecognizedException ex)
315 {
316 System.err.println("No lexical handler set in property 'http://xml.org/sax/properties/lexical-handler'");
317 }
318 catch (SAXNotSupportedException ex)
319 {
320 System.err.println("Lexical handler property not supported");
321 }
322
323 }
324
325 }