Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: gnu/xml/dom/ls/SAXEventSink.java


1   /* SAXEventSink.java -- 
2      Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
3   
4   This file is part of GNU Classpath.
5   
6   GNU Classpath is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10  
11  GNU Classpath is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  General Public License for more details.
15  
16  You should have received a copy of the GNU General Public License
17  along with GNU Classpath; see the file COPYING.  If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301 USA.
20  
21  Linking this library statically or dynamically with other modules is
22  making a combined work based on this library.  Thus, the terms and
23  conditions of the GNU General Public License cover the whole
24  combination.
25  
26  As a special exception, the copyright holders of this library give you
27  permission to link this library with independent modules to produce an
28  executable, regardless of the license terms of these independent
29  modules, and to copy and distribute the resulting executable under
30  terms of your choice, provided that you also meet, for each linked
31  independent module, the terms and conditions of the license of that
32  module.  An independent module is a module which is not derived from
33  or based on this library.  If you modify this library, you may extend
34  this exception to your version of the library, but you are not
35  obligated to do so.  If you do not wish to do so, delete this
36  exception statement from your version. */
37  
38  package gnu.xml.dom.ls;
39  
40  import java.util.Iterator;
41  import java.util.LinkedList;
42  import java.util.List;
43  import javax.xml.XMLConstants;
44  import org.w3c.dom.Attr;
45  import org.w3c.dom.DocumentType;
46  import org.w3c.dom.Element;
47  import org.w3c.dom.Entity;
48  import org.w3c.dom.NamedNodeMap;
49  import org.w3c.dom.Node;
50  import org.w3c.dom.Text;
51  import org.xml.sax.Attributes;
52  import org.xml.sax.DTDHandler;
53  import org.xml.sax.Locator;
54  import org.xml.sax.SAXException;
55  import org.xml.sax.ext.Attributes2;
56  import org.xml.sax.ext.DeclHandler;
57  import org.xml.sax.ext.LexicalHandler;
58  import gnu.xml.aelfred2.ContentHandler2;
59  import gnu.xml.dom.DomAttr;
60  import gnu.xml.dom.DomDocument;
61  import gnu.xml.dom.DomDoctype;
62  
63  /**
64   * A SAX content and lexical handler used to construct a DOM document.
65   *
66   * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
67   */
68  class SAXEventSink
69    implements ContentHandler2, LexicalHandler, DTDHandler, DeclHandler
70  {
71  
72    private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
73    private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
74  
75    boolean namespaceAware;
76    boolean ignoreWhitespace;
77    boolean expandEntityReferences;
78    boolean ignoreComments;
79    boolean coalescing;
80    
81    DomDocument doc; // document being constructed
82    Node ctx; // current context (parent node)
83    LinkedList entityCtx; // entity context
84    List pending; // namespace nodes waiting for a declaring element
85    Locator locator;
86    boolean inCDATA;
87    boolean inDTD;
88    boolean interrupted;
89  
90    void interrupt()
91    {
92      interrupted = true;
93    }
94  
95    // -- ContentHandler2 --
96    
97    public void setDocumentLocator(Locator locator)
98    {
99      this.locator = locator;
100   }
101 
102   public void startDocument()
103     throws SAXException
104   {
105     if (namespaceAware)
106       {
107         pending = new LinkedList();
108       }
109     doc = new DomDocument();
110     doc.setStrictErrorChecking(false);
111     doc.setBuilding(true);
112     ctx = doc;
113   }
114 
115   public void xmlDecl(String version, String encoding, boolean standalone,
116                       String inputEncoding)
117     throws SAXException
118   {
119     if (interrupted)
120       {
121         return;
122       }
123     doc.setXmlVersion(version);
124     doc.setXmlEncoding(encoding);
125     doc.setXmlStandalone(standalone);
126     doc.setInputEncoding(inputEncoding);
127   }
128 
129   public void endDocument()
130     throws SAXException
131   {
132     doc.setStrictErrorChecking(true);
133     doc.setBuilding(false);
134     DomDoctype doctype = (DomDoctype) doc.getDoctype();
135     if (doctype != null)
136       {
137         doctype.makeReadonly();
138       }
139     ctx = null;
140     locator = null;
141   }
142 
143   public void startPrefixMapping(String prefix, String uri)
144     throws SAXException
145   {
146     if (namespaceAware)
147       {
148         String nsName = (prefix != null && prefix.length() > 0) ?
149           XMLNS_PREFIX + ":" + prefix : XMLNS_PREFIX;
150         DomAttr ns = (DomAttr) doc.createAttributeNS(XMLNS_URI, nsName);
151         ns.setNodeValue(uri);
152         if (ctx.getNodeType() == Node.ATTRIBUTE_NODE)
153           {
154             // Add to owner element
155             Node target = ((Attr) ctx).getOwnerElement();
156             target.getAttributes().setNamedItemNS(ns);
157           }
158         else
159           {
160             // Add to pending list; namespace node will be inserted when
161             // element is seen
162             pending.add(ns);
163           }
164       }
165   }
166 
167   public void endPrefixMapping(String prefix)
168     throws SAXException
169   {
170   }
171 
172   public void startElement(String uri, String localName, String qName,
173                            Attributes atts)
174     throws SAXException
175   {
176     if (interrupted)
177       {
178         return;
179       }
180     Element element = createElement(uri, localName, qName, atts);
181     // add element to context
182     ctx.appendChild(element);
183     ctx = element;
184   }
185 
186   protected Element createElement(String uri, String localName, String qName,
187                                   Attributes atts)
188     throws SAXException
189   {
190     // create element node
191     Element element = namespaceAware ?
192       doc.createElementNS(uri, qName) :
193       doc.createElement(qName);
194     NamedNodeMap attrs = element.getAttributes();
195     if (namespaceAware && !pending.isEmpty())
196       {
197         // add pending namespace nodes
198         for (Iterator i = pending.iterator(); i.hasNext(); )
199           {
200             Node ns = (Node) i.next();
201             attrs.setNamedItemNS(ns);
202           }
203         pending.clear();
204       }
205     // add attributes
206     int len = atts.getLength();
207     for (int i = 0; i < len; i++)
208       {
209         // create attribute
210         Attr attr = createAttr(atts, i);
211         if (attr != null)
212           {
213             // add attribute to element
214             if (namespaceAware)
215               {
216                 attrs.setNamedItemNS(attr);
217               }
218             else
219               {
220                 attrs.setNamedItem(attr);
221               }
222           }
223       }
224     return element;
225   }
226 
227   protected Attr createAttr(Attributes atts, int index)
228   {
229     DomAttr attr;
230     if (namespaceAware)
231       {
232         String a_uri = atts.getURI(index);
233         String a_qName = atts.getQName(index);
234         attr = (DomAttr) doc.createAttributeNS(a_uri, a_qName);
235       }
236     else
237       {
238         String a_qName = atts.getQName(index);
239         attr = (DomAttr) doc.createAttribute(a_qName);
240       }
241     attr.setNodeValue(atts.getValue(index));
242     if (atts instanceof Attributes2)
243       {
244         Attributes2 atts2 = (Attributes2) atts;
245         // TODO attr.setDeclared(atts2.isDeclared(index));
246         attr.setSpecified(atts2.isSpecified(index));
247       }
248     return attr;
249   }
250 
251   public void endElement(String uri, String localName, String qName)
252     throws SAXException
253   {
254     if (interrupted)
255       {
256         return;
257       }
258     if (namespaceAware)
259       {
260         pending.clear();
261       }
262     ctx = ctx.getParentNode();
263   }
264 
265   public void characters(char[] c, int off, int len)
266     throws SAXException
267   {
268     if (interrupted)
269       {
270         return;
271       }
272     ctx.appendChild(createText(c, off, len));
273   }
274 
275   protected Text createText(char[] c, int off, int len)
276     throws SAXException
277   {
278     Text text = (inCDATA && !coalescing) ?
279       doc.createCDATASection(new String(c, off, len)) :
280       doc.createTextNode(new String(c, off, len));
281     return text;
282   }
283 
284   public void ignorableWhitespace(char[] c, int off, int len)
285     throws SAXException
286   {
287     if (interrupted)
288       {
289         return;
290       }
291     if (!ignoreWhitespace)
292       {
293         characters(c, off, len);
294       }
295   }
296 
297   public void processingInstruction(String target, String data)
298     throws SAXException
299   {
300     if (interrupted)
301       {
302         return;
303       }
304     if (!inDTD)
305       {
306         Node pi = createProcessingInstruction(target, data);
307         ctx.appendChild(pi);
308       }
309   }
310 
311   protected Node createProcessingInstruction(String target, String data)
312   {
313     return doc.createProcessingInstruction(target, data);
314   }
315 
316   public void skippedEntity(String name)
317     throws SAXException
318   {
319     // This callback is totally pointless
320   }
321 
322   // -- LexicalHandler --
323   
324   public void startDTD(String name, String publicId, String systemId)
325     throws SAXException
326   {
327     if (interrupted)
328       {
329         return;
330       }
331     Node doctype = createDocumentType(name, publicId, systemId);
332     doc.appendChild(doctype);
333     ctx = doctype;
334     inDTD = true;
335   }
336 
337   protected Node createDocumentType(String name, String publicId,
338                                     String systemId)
339   {
340     return new DomDoctype(doc, name, publicId, systemId);
341   }
342 
343   public void endDTD()
344     throws SAXException
345   {
346     if (interrupted)
347       {
348         return;
349       }
350     inDTD = false;
351     ctx = ctx.getParentNode();
352   }
353 
354   public void startEntity(String name)
355     throws SAXException
356   {
357     DocumentType doctype = doc.getDoctype();
358     if (doctype == null)
359       {
360         throw new SAXException("SAX parser error: " +
361                                "reference to entity in undeclared doctype");
362       }
363     if ("[dtd]".equals(name) || name.charAt(0) == '%')
364       {
365         // Ignore DTD and parameter entities
366         ctx = doctype;
367         return;
368       }
369     if ("lt".equals(name) ||
370         "gt".equals(name) ||
371         "amp".equals(name) ||
372         "apos".equals(name) ||
373         "quot".equals(name))
374       {
375         return;
376       }
377     // Get entity
378     NamedNodeMap entities = doctype.getEntities();
379     Entity entity = (Entity) entities.getNamedItem(name);
380     if (entity == null)
381       {
382         throw new SAXException("SAX parser error: " +
383                                "reference to undeclared entity: " + name);
384       }
385     pushEntity(entity);
386   }
387 
388   public void endEntity(String name)
389     throws SAXException
390   {
391     if ("[dtd]".equals(name) || name.charAt(0) == '%')
392       {
393         // Ignore DTD and parameter entities
394         return;
395       }
396     if ("lt".equals(name) ||
397         "gt".equals(name) ||
398         "amp".equals(name) ||
399         "apos".equals(name) ||
400         "quot".equals(name))
401       {
402         return;
403       }
404     // Get entity
405     Entity entity = popEntity();
406     // TODO resolve external entities to ensure that entity has content
407     if (expandEntityReferences)
408       {
409         // Get entity content
410         for (Node child = entity.getFirstChild(); child != null;
411              child = child.getNextSibling())
412           {
413             ctx.appendChild(child);
414           }
415       }
416     else
417       {
418         Node entityReference = doc.createEntityReference(name);
419         ctx.appendChild(entityReference);
420       }
421   }
422 
423   void pushEntity(Node entity)
424   {
425     if (entityCtx == null)
426       {
427         entityCtx = new LinkedList();
428       }
429     entityCtx.addLast(ctx);
430     ctx = entity;
431   }
432 
433   Entity popEntity()
434   {
435     Entity ret = (Entity) ctx;
436     ctx = (Node) entityCtx.removeLast();
437     return ret;
438   }
439 
440   public void startCDATA()
441     throws SAXException
442   {
443     inCDATA = true;
444   }
445 
446   public void endCDATA()
447     throws SAXException
448   {
449     inCDATA = false;
450   }
451 
452   public void comment(char[] c, int off, int len)
453     throws SAXException
454   {
455     if (interrupted)
456       {
457         return;
458       }
459     if (!inDTD)
460       {
461         Node comment = createComment(c, off, len);
462         ctx.appendChild(comment);
463       }
464   }
465 
466   protected Node createComment(char[] c, int off, int len)
467   {
468     return doc.createComment(new String(c, off, len));
469   }
470 
471   // -- DTDHandler --
472 
473   public void notationDecl(String name, String publicId, String systemId)
474     throws SAXException
475   {
476     if (interrupted)
477       {
478         return;
479       }
480     DomDoctype doctype = (DomDoctype) ctx;
481     doctype.declareNotation(name, publicId, systemId);
482   }
483 
484   public void unparsedEntityDecl(String name, String publicId, String systemId,
485                                  String notationName)
486     throws SAXException
487   {
488     if (interrupted)
489       {
490         return;
491       }
492     DomDoctype doctype = (DomDoctype) ctx;
493     Entity entity = doctype.declareEntity(name, publicId, systemId,
494                                           notationName);
495   }
496 
497   // -- DeclHandler --
498   
499   public void elementDecl(String name, String model)
500     throws SAXException
501   {
502     if (interrupted)
503       {
504         return;
505       }
506     // Ignore fake element declarations generated by ValidationConsumer.
507     // If an element is not really declared in the DTD it will not be
508     // declared in the document model.
509     if (!(ctx instanceof DomDoctype))
510       {
511         return;
512       }
513     DomDoctype doctype = (DomDoctype) ctx;
514     doctype.elementDecl(name, model);
515   }
516 
517   public void attributeDecl(String eName, String aName, String type,
518                             String mode, String value)
519     throws SAXException
520   {
521     if (interrupted)
522       {
523         return;
524       }
525     DomDoctype doctype = (DomDoctype) ctx;
526     doctype.attributeDecl(eName, aName, type, mode, value);
527   }
528 
529   public void internalEntityDecl(String name, String value)
530     throws SAXException
531   {
532     if (interrupted)
533       {
534         return;
535       }
536     DomDoctype doctype = (DomDoctype) ctx;
537     Entity entity = doctype.declareEntity(name, null, null, null);
538     if (entity != null)
539       {
540         Node text = doc.createTextNode(value);
541         entity.appendChild(text);
542       }
543   }
544 
545   public void externalEntityDecl(String name, String publicId, String systemId)
546     throws SAXException
547   {
548     if (interrupted)
549       {
550         return;
551       }
552     DomDoctype doctype = (DomDoctype) ctx;
553     Entity entity = doctype.declareEntity(name, publicId, systemId, null);
554   }
555   
556 }
557