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