1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70:
71:
76: public class SAXEventSink
77: implements ContentHandler, LexicalHandler, DTDHandler, DeclHandler
78: {
79:
80: private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
81: private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
82: private static final HashSet PREDEFINED_ENTITIES = new HashSet();
83: static
84: {
85: PREDEFINED_ENTITIES.add("amp");
86: PREDEFINED_ENTITIES.add("lt");
87: PREDEFINED_ENTITIES.add("gt");
88: PREDEFINED_ENTITIES.add("quot");
89: PREDEFINED_ENTITIES.add("apos");
90: }
91:
92: boolean namespaceAware;
93: boolean ignoreWhitespace;
94: boolean expandEntityReferences;
95: boolean ignoreComments;
96: boolean coalescing;
97:
98: XMLReader reader;
99:
100: DomDocument doc;
101: Node ctx;
102: LinkedList entityCtx;
103: List pending;
104: Locator locator;
105: boolean inCDATA;
106: boolean inDTD;
107: boolean interrupted;
108:
109: void interrupt()
110: {
111: interrupted = true;
112: }
113:
114: public Document getDocument()
115: {
116: return doc;
117: }
118:
119: public void setReader(XMLReader reader)
120: {
121: this.reader = reader;
122: }
123:
124:
125:
126: public void setDocumentLocator(Locator locator)
127: {
128: this.locator = locator;
129: }
130:
131: public void startDocument()
132: throws SAXException
133: {
134: if (namespaceAware)
135: {
136: pending = new LinkedList();
137: }
138: doc = new DomDocument();
139: doc.setStrictErrorChecking(false);
140: doc.setBuilding(true);
141: doc.setDefaultAttributes(false);
142: ctx = doc;
143:
144: final String FEATURES = "http://xml.org/sax/features/";
145: final String PROPERTIES = "http://xml.org/sax/properties/";
146: final String GNU_PROPERTIES = "http://gnu.org/sax/properties/";
147:
148: if (reader != null)
149: {
150: boolean standalone = reader.getFeature(FEATURES + "is-standalone");
151: doc.setXmlStandalone(standalone);
152: try
153: {
154: String version = (String) reader.getProperty(PROPERTIES +
155: "document-xml-version");
156: doc.setXmlVersion(version);
157: }
158: catch (SAXNotRecognizedException e)
159: {
160: }
161: catch (SAXNotSupportedException e)
162: {
163: }
164: try
165: {
166: String encoding = (String) reader.getProperty(GNU_PROPERTIES +
167: "document-xml-encoding");
168: doc.setXmlEncoding(encoding);
169: }
170: catch (SAXNotRecognizedException e)
171: {
172: }
173: catch (SAXNotSupportedException e)
174: {
175: }
176: }
177: if (locator != null && locator instanceof Locator2)
178: {
179: String encoding = ((Locator2) locator).getEncoding();
180: doc.setInputEncoding(encoding);
181: }
182: }
183:
184: public void endDocument()
185: throws SAXException
186: {
187: doc.setStrictErrorChecking(true);
188: doc.setBuilding(false);
189: doc.setDefaultAttributes(true);
190: DomDoctype doctype = (DomDoctype) doc.getDoctype();
191: if (doctype != null)
192: {
193: doctype.makeReadonly();
194: }
195: ctx = null;
196: locator = null;
197: }
198:
199: public void startPrefixMapping(String prefix, String uri)
200: throws SAXException
201: {
202: if (namespaceAware)
203: {
204: String nsName = (prefix != null && prefix.length() > 0) ?
205: XMLNS_PREFIX + ":" + prefix : XMLNS_PREFIX;
206: DomAttr ns = (DomAttr) doc.createAttributeNS(XMLNS_URI, nsName);
207: ns.setNodeValue(uri);
208: if (ctx.getNodeType() == Node.ATTRIBUTE_NODE)
209: {
210:
211: Node target = ((Attr) ctx).getOwnerElement();
212: target.getAttributes().setNamedItemNS(ns);
213: }
214: else
215: {
216:
217:
218: pending.add(ns);
219: }
220: }
221: }
222:
223: public void endPrefixMapping(String prefix)
224: throws SAXException
225: {
226: }
227:
228: public void startElement(String uri, String localName, String qName,
229: Attributes atts)
230: throws SAXException
231: {
232: if (interrupted)
233: {
234: return;
235: }
236: Element element = createElement(uri, localName, qName, atts);
237:
238: ctx.appendChild(element);
239: ctx = element;
240: }
241:
242: protected Element createElement(String uri, String localName, String qName,
243: Attributes atts)
244: throws SAXException
245: {
246:
247: Element element = namespaceAware ?
248: doc.createElementNS(uri, qName) :
249: doc.createElement(qName);
250: NamedNodeMap attrs = element.getAttributes();
251: if (namespaceAware && !pending.isEmpty())
252: {
253:
254: for (Iterator i = pending.iterator(); i.hasNext(); )
255: {
256: Node ns = (Node) i.next();
257: attrs.setNamedItemNS(ns);
258: }
259: pending.clear();
260: }
261:
262: int len = atts.getLength();
263: for (int i = 0; i < len; i++)
264: {
265:
266: Attr attr = createAttr(atts, i);
267: if (attr != null)
268: {
269:
270: if (namespaceAware)
271: {
272: attrs.setNamedItemNS(attr);
273: }
274: else
275: {
276: attrs.setNamedItem(attr);
277: }
278: }
279: }
280: return element;
281: }
282:
283: protected Attr createAttr(Attributes atts, int index)
284: {
285: DomAttr attr;
286: if (namespaceAware)
287: {
288: String a_uri = atts.getURI(index);
289: String a_qName = atts.getQName(index);
290: attr = (DomAttr) doc.createAttributeNS(a_uri, a_qName);
291: }
292: else
293: {
294: String a_qName = atts.getQName(index);
295: attr = (DomAttr) doc.createAttribute(a_qName);
296: }
297: attr.setNodeValue(atts.getValue(index));
298: if (atts instanceof Attributes2)
299: {
300: Attributes2 atts2 = (Attributes2) atts;
301:
302: attr.setSpecified(atts2.isSpecified(index));
303: }
304: return attr;
305: }
306:
307: public void endElement(String uri, String localName, String qName)
308: throws SAXException
309: {
310: if (interrupted)
311: {
312: return;
313: }
314: if (namespaceAware)
315: {
316: pending.clear();
317: }
318: ctx = ctx.getParentNode();
319: }
320:
321: public void characters(char[] c, int off, int len)
322: throws SAXException
323: {
324: if (interrupted || len < 1)
325: {
326: return;
327: }
328: ctx.appendChild(createText(c, off, len));
329: }
330:
331: protected Text createText(char[] c, int off, int len)
332: throws SAXException
333: {
334: Text text = (inCDATA && !coalescing) ?
335: doc.createCDATASection(new String(c, off, len)) :
336: doc.createTextNode(new String(c, off, len));
337: return text;
338: }
339:
340: public void ignorableWhitespace(char[] c, int off, int len)
341: throws SAXException
342: {
343: if (interrupted)
344: {
345: return;
346: }
347: if (!ignoreWhitespace)
348: {
349: characters(c, off, len);
350: }
351: }
352:
353: public void processingInstruction(String target, String data)
354: throws SAXException
355: {
356: if (interrupted)
357: {
358: return;
359: }
360: Node pi = createProcessingInstruction(target, data);
361: ctx.appendChild(pi);
362: }
363:
364: protected Node createProcessingInstruction(String target, String data)
365: {
366: return doc.createProcessingInstruction(target, data);
367: }
368:
369: public void skippedEntity(String name)
370: throws SAXException
371: {
372:
373: }
374:
375:
376:
377: public void startDTD(String name, String publicId, String systemId)
378: throws SAXException
379: {
380: if (interrupted)
381: {
382: return;
383: }
384: Node doctype = createDocumentType(name, publicId, systemId);
385: doc.appendChild(doctype);
386: ctx = doctype;
387: inDTD = true;
388: }
389:
390: protected Node createDocumentType(String name, String publicId,
391: String systemId)
392: {
393: return new DomDoctype(doc, name, publicId, systemId);
394: }
395:
396: public void endDTD()
397: throws SAXException
398: {
399: if (interrupted)
400: {
401: return;
402: }
403: inDTD = false;
404: ctx = ctx.getParentNode();
405: }
406:
407: public void startEntity(String name)
408: throws SAXException
409: {
410: if (interrupted)
411: return;
412: DocumentType doctype = doc.getDoctype();
413: if (doctype == null)
414: {
415: throw new SAXException("SAX parser error: " +
416: "reference to entity in undeclared doctype");
417: }
418: if ("[dtd]".equals(name) || name.charAt(0) == '%')
419: return;
420: if (PREDEFINED_ENTITIES.contains(name))
421: return;
422:
423: NamedNodeMap entities = doctype.getEntities();
424: Entity entity = (Entity) entities.getNamedItem(name);
425: if (entity == null)
426: {
427: throw new SAXException("SAX parser error: " +
428: "reference to undeclared entity: " + name);
429: }
430: EntityReference ref = doc.createEntityReference(name);
431:
432: Node child = ref.getFirstChild();
433: while (child != null)
434: {
435: Node nextChild = child.getNextSibling();
436: ref.removeChild(child);
437: child = nextChild;
438: }
439: ctx.appendChild(ref);
440: ctx = ref;
441: }
442:
443: public void endEntity(String name)
444: throws SAXException
445: {
446: if (interrupted)
447: return;
448: if ("[dtd]".equals(name) || name.charAt(0) == '%')
449: return;
450: if (PREDEFINED_ENTITIES.contains(name))
451: return;
452:
453: EntityReference ref = (EntityReference) ctx;
454: if (!ref.getNodeName().equals(name))
455: throw new SAXException("expecting end of "+ref.getNodeName()+" entity");
456: ctx = ctx.getParentNode();
457: if (ref instanceof DomNode)
458: ((DomNode) ref).makeReadonly();
459: if (expandEntityReferences)
460: {
461:
462: Node child = ref.getFirstChild();
463: while (child != null)
464: {
465: Node nextChild = child.getNextSibling();
466: ctx.appendChild(child);
467: child = nextChild;
468: }
469: ctx.removeChild(ref);
470: }
471: }
472:
473: public void startCDATA()
474: throws SAXException
475: {
476: inCDATA = true;
477: }
478:
479: public void endCDATA()
480: throws SAXException
481: {
482: inCDATA = false;
483: }
484:
485: public void comment(char[] c, int off, int len)
486: throws SAXException
487: {
488: if (interrupted)
489: {
490: return;
491: }
492: Node comment = createComment(c, off, len);
493: ctx.appendChild(comment);
494: }
495:
496: protected Node createComment(char[] c, int off, int len)
497: {
498: return doc.createComment(new String(c, off, len));
499: }
500:
501:
502:
503: public void notationDecl(String name, String publicId, String systemId)
504: throws SAXException
505: {
506: if (interrupted)
507: {
508: return;
509: }
510: if (!inDTD)
511: throw new SAXException("notation decl outside DTD");
512: DomDoctype doctype = (DomDoctype) ctx;
513: doctype.declareNotation(name, publicId, systemId);
514: }
515:
516: public void unparsedEntityDecl(String name, String publicId, String systemId,
517: String notationName)
518: throws SAXException
519: {
520: if (interrupted)
521: {
522: return;
523: }
524: if (!inDTD)
525: throw new SAXException("unparsed entity decl outside DTD");
526: DomDoctype doctype = (DomDoctype) ctx;
527: Entity entity = doctype.declareEntity(name, publicId, systemId,
528: notationName);
529: }
530:
531:
532:
533: public void elementDecl(String name, String model)
534: throws SAXException
535: {
536: if (interrupted)
537: {
538: return;
539: }
540: if (!inDTD)
541: throw new SAXException("element decl outside DTD");
542:
543:
544:
545: if (!(ctx instanceof DomDoctype))
546: {
547: return;
548: }
549: DomDoctype doctype = (DomDoctype) ctx;
550: doctype.elementDecl(name, model);
551: }
552:
553: public void attributeDecl(String eName, String aName, String type,
554: String mode, String value)
555: throws SAXException
556: {
557: if (interrupted)
558: {
559: return;
560: }
561: if (!inDTD)
562: throw new SAXException("attribute decl outside DTD");
563: DomDoctype doctype = (DomDoctype) ctx;
564: doctype.attributeDecl(eName, aName, type, mode, value);
565: }
566:
567: public void internalEntityDecl(String name, String value)
568: throws SAXException
569: {
570: if (interrupted)
571: {
572: return;
573: }
574: if (!inDTD)
575: throw new SAXException("internal entity decl outside DTD");
576: DomDoctype doctype = (DomDoctype) ctx;
577: Entity entity = doctype.declareEntity(name, null, null, null);
578: if (entity != null)
579: {
580: Node text = doc.createTextNode(value);
581: entity.appendChild(text);
582: }
583: }
584:
585: public void externalEntityDecl(String name, String publicId, String systemId)
586: throws SAXException
587: {
588: if (interrupted)
589: {
590: return;
591: }
592: if (!inDTD)
593: throw new SAXException("external entity decl outside DTD");
594: DomDoctype doctype = (DomDoctype) ctx;
595: Entity entity = doctype.declareEntity(name, publicId, systemId, null);
596: }
597:
598: }