KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dom4j > io > SAXContentHandler


1 /*
2  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3  *
4  * This software is open source.
5  * See the bottom of this file for the licence.
6  */

7
8 package org.dom4j.io;
9
10 import java.lang.reflect.Method JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.dom4j.Branch;
17 import org.dom4j.Document;
18 import org.dom4j.DocumentFactory;
19 import org.dom4j.DocumentType;
20 import org.dom4j.Element;
21 import org.dom4j.ElementHandler;
22 import org.dom4j.Namespace;
23 import org.dom4j.QName;
24 import org.dom4j.dtd.AttributeDecl;
25 import org.dom4j.dtd.ElementDecl;
26 import org.dom4j.dtd.ExternalEntityDecl;
27 import org.dom4j.dtd.InternalEntityDecl;
28 import org.dom4j.tree.AbstractElement;
29 import org.dom4j.tree.NamespaceStack;
30
31 import org.xml.sax.Attributes JavaDoc;
32 import org.xml.sax.DTDHandler JavaDoc;
33 import org.xml.sax.EntityResolver JavaDoc;
34 import org.xml.sax.InputSource JavaDoc;
35 import org.xml.sax.Locator JavaDoc;
36 import org.xml.sax.SAXException JavaDoc;
37 import org.xml.sax.SAXParseException JavaDoc;
38 import org.xml.sax.ext.DeclHandler JavaDoc;
39 import org.xml.sax.ext.LexicalHandler JavaDoc;
40 import org.xml.sax.helpers.DefaultHandler JavaDoc;
41
42 /**
43  * <p>
44  * <code>SAXContentHandler</code> builds a dom4j tree via SAX events.
45  * </p>
46  *
47  * @author <a HREF="mailto:jstrachan@apache.org">James Strachan </a>
48  * @version $Revision: 1.61 $
49  */

50 public class SAXContentHandler extends DefaultHandler JavaDoc implements
51         LexicalHandler JavaDoc, DeclHandler JavaDoc, DTDHandler JavaDoc {
52     /** The factory used to create new <code>Document</code> instances */
53     private DocumentFactory documentFactory;
54
55     /** The document that is being built */
56     private Document document;
57
58     /** stack of <code>Element</code> objects */
59     private ElementStack elementStack;
60
61     /** stack of <code>Namespace</code> and <code>QName</code> objects */
62     private NamespaceStack namespaceStack;
63
64     /** the <code>ElementHandler</code> called as the elements are complete */
65     private ElementHandler elementHandler;
66
67     /** the Locator */
68     private Locator JavaDoc locator;
69
70     /** The name of the current entity */
71     private String JavaDoc entity;
72
73     /** Flag used to indicate that we are inside a DTD section */
74     private boolean insideDTDSection;
75
76     /** Flag used to indicate that we are inside a CDATA section */
77     private boolean insideCDATASection;
78
79     /**
80      * buffer to hold contents of cdata section across multiple characters
81      * events
82      */

83     private StringBuffer JavaDoc cdataText;
84
85     /** namespaces that are available for use */
86     private Map JavaDoc availableNamespaceMap = new HashMap JavaDoc();
87
88     /** declared namespaces that are not yet available for use */
89     private List JavaDoc declaredNamespaceList = new ArrayList JavaDoc();
90
91     /** internal DTD declarations */
92     private List JavaDoc internalDTDDeclarations;
93
94     /** external DTD declarations */
95     private List JavaDoc externalDTDDeclarations;
96
97     /** The number of namespaces that are declared in the current scope */
98     private int declaredNamespaceIndex;
99
100     /** The entity resolver */
101     private EntityResolver JavaDoc entityResolver;
102
103     private InputSource JavaDoc inputSource;
104
105     /** The current element we are on */
106     private Element currentElement;
107
108     /** Should internal DTD declarations be expanded into a List in the DTD */
109     private boolean includeInternalDTDDeclarations = false;
110
111     /** Should external DTD declarations be expanded into a List in the DTD */
112     private boolean includeExternalDTDDeclarations = false;
113
114     /** The number of levels deep we are inside a startEntity/endEntity call */
115     private int entityLevel;
116
117     /** Are we in an internal DTD subset? */
118     private boolean internalDTDsubset = false;
119
120     /** Whether adjacent text nodes should be merged */
121     private boolean mergeAdjacentText = false;
122
123     /** Have we added text to the buffer */
124     private boolean textInTextBuffer = false;
125
126     /** Should we ignore comments */
127     private boolean ignoreComments = false;
128
129     /** Buffer used to concatenate text together */
130     private StringBuffer JavaDoc textBuffer;
131
132     /** Holds value of property stripWhitespaceText. */
133     private boolean stripWhitespaceText = false;
134
135     public SAXContentHandler() {
136         this(DocumentFactory.getInstance());
137     }
138
139     public SAXContentHandler(DocumentFactory documentFactory) {
140         this(documentFactory, null);
141     }
142
143     public SAXContentHandler(DocumentFactory documentFactory,
144             ElementHandler elementHandler) {
145         this(documentFactory, elementHandler, null);
146         this.elementStack = createElementStack();
147     }
148
149     public SAXContentHandler(DocumentFactory documentFactory,
150             ElementHandler elementHandler, ElementStack elementStack) {
151         this.documentFactory = documentFactory;
152         this.elementHandler = elementHandler;
153         this.elementStack = elementStack;
154         this.namespaceStack = new NamespaceStack(documentFactory);
155     }
156
157     /**
158      * DOCUMENT ME!
159      *
160      * @return the document that has been or is being built
161      */

162     public Document getDocument() {
163         if (document == null) {
164             document = createDocument();
165         }
166
167         return document;
168     }
169
170     // ContentHandler interface
171
// -------------------------------------------------------------------------
172
public void setDocumentLocator(Locator JavaDoc documentLocator) {
173         this.locator = documentLocator;
174     }
175
176     public void processingInstruction(String JavaDoc target, String JavaDoc data)
177             throws SAXException JavaDoc {
178         if (mergeAdjacentText && textInTextBuffer) {
179             completeCurrentTextNode();
180         }
181
182         if (currentElement != null) {
183             currentElement.addProcessingInstruction(target, data);
184         } else {
185             getDocument().addProcessingInstruction(target, data);
186         }
187     }
188
189     public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri)
190             throws SAXException JavaDoc {
191         namespaceStack.push(prefix, uri);
192     }
193
194     public void endPrefixMapping(String JavaDoc prefix) throws SAXException JavaDoc {
195         namespaceStack.pop(prefix);
196         declaredNamespaceIndex = namespaceStack.size();
197     }
198
199     public void startDocument() throws SAXException JavaDoc {
200         // document = createDocument();
201
document = null;
202         currentElement = null;
203
204         elementStack.clear();
205
206         if ((elementHandler != null)
207                 && (elementHandler instanceof DispatchHandler)) {
208             elementStack.setDispatchHandler((DispatchHandler) elementHandler);
209         }
210
211         namespaceStack.clear();
212         declaredNamespaceIndex = 0;
213
214         if (mergeAdjacentText && (textBuffer == null)) {
215             textBuffer = new StringBuffer JavaDoc();
216         }
217
218         textInTextBuffer = false;
219     }
220
221     public void endDocument() throws SAXException JavaDoc {
222         namespaceStack.clear();
223         elementStack.clear();
224         currentElement = null;
225         textBuffer = null;
226     }
227
228     public void startElement(String JavaDoc namespaceURI, String JavaDoc localName,
229             String JavaDoc qualifiedName, Attributes JavaDoc attributes) throws SAXException JavaDoc {
230         if (mergeAdjacentText && textInTextBuffer) {
231             completeCurrentTextNode();
232         }
233
234         QName qName = namespaceStack.getQName(namespaceURI, localName,
235                 qualifiedName);
236
237         Branch branch = currentElement;
238
239         if (branch == null) {
240             branch = getDocument();
241         }
242
243         Element element = branch.addElement(qName);
244
245         // add all declared namespaces
246
addDeclaredNamespaces(element);
247
248         // now lets add all attribute values
249
addAttributes(element, attributes);
250
251         elementStack.pushElement(element);
252         currentElement = element;
253
254         entity = null; // fixes bug527062
255

256         if (elementHandler != null) {
257             elementHandler.onStart(elementStack);
258         }
259     }
260
261     public void endElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName)
262             throws SAXException JavaDoc {
263         if (mergeAdjacentText && textInTextBuffer) {
264             completeCurrentTextNode();
265         }
266
267         if ((elementHandler != null) && (currentElement != null)) {
268             elementHandler.onEnd(elementStack);
269         }
270
271         elementStack.popElement();
272         currentElement = elementStack.peekElement();
273     }
274
275     public void characters(char[] ch, int start, int end) throws SAXException JavaDoc {
276         if (end == 0) {
277             return;
278         }
279
280         if (currentElement != null) {
281             if (entity != null) {
282                 if (mergeAdjacentText && textInTextBuffer) {
283                     completeCurrentTextNode();
284                 }
285
286                 currentElement.addEntity(entity, new String JavaDoc(ch, start, end));
287                 entity = null;
288             } else if (insideCDATASection) {
289                 if (mergeAdjacentText && textInTextBuffer) {
290                     completeCurrentTextNode();
291                 }
292
293                 cdataText.append(new String JavaDoc(ch, start, end));
294             } else {
295                 if (mergeAdjacentText) {
296                     textBuffer.append(ch, start, end);
297                     textInTextBuffer = true;
298                 } else {
299                     currentElement.addText(new String JavaDoc(ch, start, end));
300                 }
301             }
302         }
303     }
304
305     // ErrorHandler interface
306
// -------------------------------------------------------------------------
307

308     /**
309      * This method is called when a warning occurs during the parsing of the
310      * document. This method does nothing.
311      *
312      * @param exception
313      * DOCUMENT ME!
314      *
315      * @throws SAXException
316      * DOCUMENT ME!
317      */

318     public void warning(SAXParseException JavaDoc exception) throws SAXException JavaDoc {
319         // ignore warnings by default
320
}
321
322     /**
323      * This method is called when an error is detected during parsing such as a
324      * validation error. This method rethrows the exception
325      *
326      * @param exception
327      * DOCUMENT ME!
328      *
329      * @throws SAXException
330      * DOCUMENT ME!
331      */

332     public void error(SAXParseException JavaDoc exception) throws SAXException JavaDoc {
333         throw exception;
334     }
335
336     /**
337      * This method is called when a fatal error occurs during parsing. This
338      * method rethrows the exception
339      *
340      * @param exception
341      * DOCUMENT ME!
342      *
343      * @throws SAXException
344      * DOCUMENT ME!
345      */

346     public void fatalError(SAXParseException JavaDoc exception) throws SAXException JavaDoc {
347         throw exception;
348     }
349
350     // LexicalHandler interface
351
// -------------------------------------------------------------------------
352
public void startDTD(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId)
353             throws SAXException JavaDoc {
354         getDocument().addDocType(name, publicId, systemId);
355         insideDTDSection = true;
356         internalDTDsubset = true;
357     }
358
359     public void endDTD() throws SAXException JavaDoc {
360         insideDTDSection = false;
361
362         DocumentType docType = getDocument().getDocType();
363
364         if (docType != null) {
365             if (internalDTDDeclarations != null) {
366                 docType.setInternalDeclarations(internalDTDDeclarations);
367             }
368
369             if (externalDTDDeclarations != null) {
370                 docType.setExternalDeclarations(externalDTDDeclarations);
371             }
372         }
373
374         internalDTDDeclarations = null;
375         externalDTDDeclarations = null;
376     }
377
378     public void startEntity(String JavaDoc name) throws SAXException JavaDoc {
379         ++entityLevel;
380
381         // Ignore DTD references
382
entity = null;
383
384         if (!insideDTDSection) {
385             if (!isIgnorableEntity(name)) {
386                 entity = name;
387             }
388         }
389
390         // internal DTD subsets can only appear outside of a
391
// startEntity/endEntity block
392
// see the startDTD method in
393
// http://dom4j.org/javadoc/org/xml/sax/ext/LexicalHandler.html
394
internalDTDsubset = false;
395     }
396
397     public void endEntity(String JavaDoc name) throws SAXException JavaDoc {
398         --entityLevel;
399         entity = null;
400
401         if (entityLevel == 0) {
402             internalDTDsubset = true;
403         }
404     }
405
406     public void startCDATA() throws SAXException JavaDoc {
407         insideCDATASection = true;
408         cdataText = new StringBuffer JavaDoc();
409     }
410
411     public void endCDATA() throws SAXException JavaDoc {
412         insideCDATASection = false;
413         currentElement.addCDATA(cdataText.toString());
414     }
415
416     public void comment(char[] ch, int start, int end) throws SAXException JavaDoc {
417         if (!ignoreComments) {
418             if (mergeAdjacentText && textInTextBuffer) {
419                 completeCurrentTextNode();
420             }
421
422             String JavaDoc text = new String JavaDoc(ch, start, end);
423
424             if (!insideDTDSection && (text.length() > 0)) {
425                 if (currentElement != null) {
426                     currentElement.addComment(text);
427                 } else {
428                     getDocument().addComment(text);
429                 }
430             }
431         }
432     }
433
434     // DeclHandler interface
435
// -------------------------------------------------------------------------
436

437     /**
438      * Report an element type declaration.
439      *
440      * <p>
441      * The content model will consist of the string "EMPTY", the string "ANY",
442      * or a parenthesised group, optionally followed by an occurrence indicator.
443      * The model will be normalized so that all parameter entities are fully
444      * resolved and all whitespace is removed,and will include the enclosing
445      * parentheses. Other normalization (such as removing redundant parentheses
446      * or simplifying occurrence indicators) is at the discretion of the parser.
447      * </p>
448      *
449      * @param name
450      * The element type name.
451      * @param model
452      * The content model as a normalized string.
453      *
454      * @exception SAXException
455      * The application may raise an exception.
456      */

457     public void elementDecl(String JavaDoc name, String JavaDoc model) throws SAXException JavaDoc {
458         if (internalDTDsubset) {
459             if (includeInternalDTDDeclarations) {
460                 addDTDDeclaration(new ElementDecl(name, model));
461             }
462         } else {
463             if (includeExternalDTDDeclarations) {
464                 addExternalDTDDeclaration(new ElementDecl(name, model));
465             }
466         }
467     }
468
469     /**
470      * Report an attribute type declaration.
471      *
472      * <p>
473      * Only the effective (first) declaration for an attribute will be reported.
474      * The type will be one of the strings "CDATA", "ID", "IDREF", "IDREFS",
475      * "NMTOKEN", "NMTOKENS", "ENTITY", "ENTITIES", a parenthesized token group
476      * with the separator "|" and all whitespace removed, or the word "NOTATION"
477      * followed by a space followed by a parenthesized token group with all
478      * whitespace removed.
479      * </p>
480      *
481      * <p>
482      * Any parameter entities in the attribute value will be expanded, but
483      * general entities will not.
484      * </p>
485      *
486      * @param eName
487      * The name of the associated element.
488      * @param aName
489      * The name of the attribute.
490      * @param type
491      * A string representing the attribute type.
492      * @param valueDefault
493      * A string representing the attribute default ("#IMPLIED",
494      * "#REQUIRED", or "#FIXED") or null if none of these applies.
495      * @param val
496      * A string representing the attribute's default value, or null
497      * if there is none.
498      *
499      * @exception SAXException
500      * The application may raise an exception.
501      */

502     public void attributeDecl(String JavaDoc eName, String JavaDoc aName, String JavaDoc type,
503             String JavaDoc valueDefault, String JavaDoc val) throws SAXException JavaDoc {
504         if (internalDTDsubset) {
505             if (includeInternalDTDDeclarations) {
506                 addDTDDeclaration(new AttributeDecl(eName, aName, type,
507                         valueDefault, val));
508             }
509         } else {
510             if (includeExternalDTDDeclarations) {
511                 addExternalDTDDeclaration(new AttributeDecl(eName, aName, type,
512                         valueDefault, val));
513             }
514         }
515     }
516
517     /**
518      * Report an internal entity declaration.
519      *
520      * <p>
521      * Only the effective (first) declaration for each entity will be reported.
522      * All parameter entities in the value will be expanded, but general
523      * entities will not.
524      * </p>
525      *
526      * @param name
527      * The name of the entity. If it is a parameter entity, the name
528      * will begin with '%'.
529      * @param value
530      * The replacement text of the entity.
531      *
532      * @exception SAXException
533      * The application may raise an exception.
534      *
535      * @see #externalEntityDecl
536      * @see org.xml.sax.DTDHandler#unparsedEntityDecl
537      */

538     public void internalEntityDecl(String JavaDoc name, String JavaDoc value)
539             throws SAXException JavaDoc {
540         if (internalDTDsubset) {
541             if (includeInternalDTDDeclarations) {
542                 addDTDDeclaration(new InternalEntityDecl(name, value));
543             }
544         } else {
545             if (includeExternalDTDDeclarations) {
546                 addExternalDTDDeclaration(new InternalEntityDecl(name, value));
547             }
548         }
549     }
550
551     /**
552      * Report a parsed external entity declaration.
553      *
554      * <p>
555      * Only the effective (first) declaration for each entity will be reported.
556      * </p>
557      *
558      * @param name
559      * The name of the entity. If it is a parameter entity, the name
560      * will begin with '%'.
561      * @param publicId
562      * The declared public identifier of the entity, or null if none
563      * was declared.
564      * @param sysId
565      * The declared system identifier of the entity.
566      *
567      * @exception SAXException
568      * The application may raise an exception.
569      *
570      * @see #internalEntityDecl
571      * @see org.xml.sax.DTDHandler#unparsedEntityDecl
572      */

573     public void externalEntityDecl(String JavaDoc name, String JavaDoc publicId, String JavaDoc sysId)
574             throws SAXException JavaDoc {
575         ExternalEntityDecl declaration = new ExternalEntityDecl(name, publicId,
576                 sysId);
577
578         if (internalDTDsubset) {
579             if (includeInternalDTDDeclarations) {
580                 addDTDDeclaration(declaration);
581             }
582         } else {
583             if (includeExternalDTDDeclarations) {
584                 addExternalDTDDeclaration(declaration);
585             }
586         }
587     }
588
589     // DTDHandler interface
590
// -------------------------------------------------------------------------
591

592     /**
593      * Receive notification of a notation declaration event.
594      *
595      * <p>
596      * It is up to the application to record the notation for later reference,
597      * if necessary.
598      * </p>
599      *
600      * <p>
601      * At least one of publicId and systemId must be non-null. If a system
602      * identifier is present, and it is a URL, the SAX parser must resolve it
603      * fully before passing it to the application through this event.
604      * </p>
605      *
606      * <p>
607      * There is no guarantee that the notation declaration will be reported
608      * before any unparsed entities that use it.
609      * </p>
610      *
611      * @param name
612      * The notation name.
613      * @param publicId
614      * The notation's public identifier, or null if none was given.
615      * @param systemId
616      * The notation's system identifier, or null if none was given.
617      *
618      * @exception SAXException
619      * Any SAX exception, possibly wrapping another exception.
620      *
621      * @see #unparsedEntityDecl
622      * @see org.xml.sax.AttributeList
623      */

624     public void notationDecl(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId)
625             throws SAXException JavaDoc {
626         // #### not supported yet!
627
}
628
629     /**
630      * Receive notification of an unparsed entity declaration event.
631      *
632      * <p>
633      * Note that the notation name corresponds to a notation reported by the
634      * {@link #notationDecl notationDecl}event. It is up to the application to
635      * record the entity for later reference, if necessary.
636      * </p>
637      *
638      * <p>
639      * If the system identifier is a URL, the parser must resolve it fully
640      * before passing it to the application.
641      * </p>
642      *
643      * @param name
644      * The unparsed entity's name.
645      * @param publicId
646      * The entity's public identifier, or null if none was given.
647      * @param systemId
648      * The entity's system identifier.
649      * @param notationName
650      * The name of the associated notation.
651      *
652      * @exception SAXException
653      * Any SAX exception, possibly wrapping another exception.
654      *
655      * @see #notationDecl
656      * @see org.xml.sax.AttributeList
657      */

658     public void unparsedEntityDecl(String JavaDoc name, String JavaDoc publicId,
659             String JavaDoc systemId, String JavaDoc notationName) throws SAXException JavaDoc {
660         // #### not supported yet!
661
}
662
663     // Properties
664
// -------------------------------------------------------------------------
665
public ElementStack getElementStack() {
666         return elementStack;
667     }
668
669     public void setElementStack(ElementStack elementStack) {
670         this.elementStack = elementStack;
671     }
672
673     public EntityResolver JavaDoc getEntityResolver() {
674         return entityResolver;
675     }
676
677     public void setEntityResolver(EntityResolver JavaDoc entityResolver) {
678         this.entityResolver = entityResolver;
679     }
680
681     public InputSource JavaDoc getInputSource() {
682         return inputSource;
683     }
684
685     public void setInputSource(InputSource JavaDoc inputSource) {
686         this.inputSource = inputSource;
687     }
688
689     /**
690      * DOCUMENT ME!
691      *
692      * @return whether internal DTD declarations should be expanded into the
693      * DocumentType object or not.
694      */

695     public boolean isIncludeInternalDTDDeclarations() {
696         return includeInternalDTDDeclarations;
697     }
698
699     /**
700      * Sets whether internal DTD declarations should be expanded into the
701      * DocumentType object or not.
702      *
703      * @param include
704      * whether or not DTD declarations should be expanded and
705      * included into the DocumentType object.
706      */

707     public void setIncludeInternalDTDDeclarations(boolean include) {
708         this.includeInternalDTDDeclarations = include;
709     }
710
711     /**
712      * DOCUMENT ME!
713      *
714      * @return whether external DTD declarations should be expanded into the
715      * DocumentType object or not.
716      */

717     public boolean isIncludeExternalDTDDeclarations() {
718         return includeExternalDTDDeclarations;
719     }
720
721     /**
722      * Sets whether DTD external declarations should be expanded into the
723      * DocumentType object or not.
724      *
725      * @param include
726      * whether or not DTD declarations should be expanded and
727      * included into the DocumentType object.
728      */

729     public void setIncludeExternalDTDDeclarations(boolean include) {
730         this.includeExternalDTDDeclarations = include;
731     }
732
733     /**
734      * Returns whether adjacent text nodes should be merged together.
735      *
736      * @return Value of property mergeAdjacentText.
737      */

738     public boolean isMergeAdjacentText() {
739         return mergeAdjacentText;
740     }
741
742     /**
743      * Sets whether or not adjacent text nodes should be merged together when
744      * parsing.
745      *
746      * @param mergeAdjacentText
747      * New value of property mergeAdjacentText.
748      */

749     public void setMergeAdjacentText(boolean mergeAdjacentText) {
750         this.mergeAdjacentText = mergeAdjacentText;
751     }
752
753     /**
754      * Sets whether whitespace between element start and end tags should be
755      * ignored
756      *
757      * @return Value of property stripWhitespaceText.
758      */

759     public boolean isStripWhitespaceText() {
760         return stripWhitespaceText;
761     }
762
763     /**
764      * Sets whether whitespace between element start and end tags should be
765      * ignored.
766      *
767      * @param stripWhitespaceText
768      * New value of property stripWhitespaceText.
769      */

770     public void setStripWhitespaceText(boolean stripWhitespaceText) {
771         this.stripWhitespaceText = stripWhitespaceText;
772     }
773
774     /**
775      * Returns whether we should ignore comments or not.
776      *
777      * @return boolean
778      */

779     public boolean isIgnoreComments() {
780         return ignoreComments;
781     }
782
783     /**
784      * Sets whether we should ignore comments or not.
785      *
786      * @param ignoreComments
787      * whether we should ignore comments or not.
788      */

789     public void setIgnoreComments(boolean ignoreComments) {
790         this.ignoreComments = ignoreComments;
791     }
792
793     // Implementation methods
794
// -------------------------------------------------------------------------
795

796     /**
797      * If the current text buffer contains any text then create a new text node
798      * with it and add it to the current element
799      */

800     protected void completeCurrentTextNode() {
801         if (stripWhitespaceText) {
802             boolean whitespace = true;
803
804             for (int i = 0, size = textBuffer.length(); i < size; i++) {
805                 if (!Character.isWhitespace(textBuffer.charAt(i))) {
806                     whitespace = false;
807
808                     break;
809                 }
810             }
811
812             if (!whitespace) {
813                 currentElement.addText(textBuffer.toString());
814             }
815         } else {
816             currentElement.addText(textBuffer.toString());
817         }
818
819         textBuffer.setLength(0);
820         textInTextBuffer = false;
821     }
822
823     /**
824      * DOCUMENT ME!
825      *
826      * @return the current document
827      */

828     protected Document createDocument() {
829         String JavaDoc encoding = getEncoding();
830         Document doc = documentFactory.createDocument(encoding);
831
832         // set the EntityResolver
833
doc.setEntityResolver(entityResolver);
834
835         if (inputSource != null) {
836             doc.setName(inputSource.getSystemId());
837         }
838
839         return doc;
840     }
841
842     private String JavaDoc getEncoding() {
843         if (locator == null) {
844             return null;
845         }
846
847         // use reflection to avoid dependency on Locator2
848
// or other locator implemenations.
849
try {
850             Method JavaDoc m = locator.getClass().getMethod("getEncoding",
851                     new Class JavaDoc[] {});
852
853             if (m != null) {
854                 return (String JavaDoc) m.invoke(locator, null);
855             }
856         } catch (Exception JavaDoc e) {
857             // do nothing
858
}
859
860         // couldn't determine encoding, returning null...
861
return null;
862     }
863
864     /**
865      * a Strategy Method to determine if a given entity name is ignorable
866      *
867      * @param name
868      * DOCUMENT ME!
869      *
870      * @return DOCUMENT ME!
871      */

872     protected boolean isIgnorableEntity(String JavaDoc name) {
873         return "amp".equals(name) || "apos".equals(name) || "gt".equals(name)
874                 || "lt".equals(name) || "quot".equals(name);
875     }
876
877     /**
878      * Add all namespaces declared before the startElement() SAX event to the
879      * current element so that they are available to child elements and
880      * attributes
881      *
882      * @param element
883      * DOCUMENT ME!
884      */

885     protected void addDeclaredNamespaces(Element element) {
886         Namespace elementNamespace = element.getNamespace();
887
888         for (int size = namespaceStack.size(); declaredNamespaceIndex < size;
889                 declaredNamespaceIndex++) {
890             Namespace namespace = namespaceStack
891                     .getNamespace(declaredNamespaceIndex);
892
893             // if ( namespace != elementNamespace ) {
894
element.add(namespace);
895
896             // }
897
}
898     }
899
900     /**
901      * Add all the attributes to the given elements
902      *
903      * @param element
904      * DOCUMENT ME!
905      * @param attributes
906      * DOCUMENT ME!
907      */

908     protected void addAttributes(Element element, Attributes JavaDoc attributes) {
909         // XXXX: as an optimisation, we could deduce this value from the current
910
// SAX parser settings, the SAX namespaces-prefixes feature
911
boolean noNamespaceAttributes = false;
912
913         if (element instanceof AbstractElement) {
914             // optimised method
915
AbstractElement baseElement = (AbstractElement) element;
916             baseElement.setAttributes(attributes, namespaceStack,
917                     noNamespaceAttributes);
918         } else {
919             int size = attributes.getLength();
920
921             for (int i = 0; i < size; i++) {
922                 String JavaDoc attributeQName = attributes.getQName(i);
923
924                 if (noNamespaceAttributes
925                         || !attributeQName.startsWith("xmlns")) {
926                     String JavaDoc attributeURI = attributes.getURI(i);
927                     String JavaDoc attributeLocalName = attributes.getLocalName(i);
928                     String JavaDoc attributeValue = attributes.getValue(i);
929
930                     QName qName = namespaceStack.getAttributeQName(
931                             attributeURI, attributeLocalName, attributeQName);
932                     element.addAttribute(qName, attributeValue);
933                 }
934             }
935         }
936     }
937
938     /**
939      * Adds an internal DTD declaration to the list of declarations
940      *
941      * @param declaration
942      * DOCUMENT ME!
943      */

944     protected void addDTDDeclaration(Object JavaDoc declaration) {
945         if (internalDTDDeclarations == null) {
946             internalDTDDeclarations = new ArrayList JavaDoc();
947         }
948
949         internalDTDDeclarations.add(declaration);
950     }
951
952     /**
953      * Adds an external DTD declaration to the list of declarations
954      *
955      * @param declaration
956      * DOCUMENT ME!
957      */

958     protected void addExternalDTDDeclaration(Object JavaDoc declaration) {
959         if (externalDTDDeclarations == null) {
960             externalDTDDeclarations = new ArrayList JavaDoc();
961         }
962
963         externalDTDDeclarations.add(declaration);
964     }
965
966     protected ElementStack createElementStack() {
967         return new ElementStack();
968     }
969 }
970
971 /*
972  * Redistribution and use of this software and associated documentation
973  * ("Software"), with or without modification, are permitted provided that the
974  * following conditions are met:
975  *
976  * 1. Redistributions of source code must retain copyright statements and
977  * notices. Redistributions must also contain a copy of this document.
978  *
979  * 2. Redistributions in binary form must reproduce the above copyright notice,
980  * this list of conditions and the following disclaimer in the documentation
981  * and/or other materials provided with the distribution.
982  *
983  * 3. The name "DOM4J" must not be used to endorse or promote products derived
984  * from this Software without prior written permission of MetaStuff, Ltd. For
985  * written permission, please contact dom4j-info@metastuff.com.
986  *
987  * 4. Products derived from this Software may not be called "DOM4J" nor may
988  * "DOM4J" appear in their names without prior written permission of MetaStuff,
989  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
990  *
991  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
992  *
993  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
994  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
995  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
996  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
997  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
998  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
999  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1000 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1001 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1002 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1003 * POSSIBILITY OF SUCH DAMAGE.
1004 *
1005 * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
1006 */

1007
Popular Tags