1
2
3
4
5
6
7
8 package org.dom4j.io;
9
10 import java.io.IOException;
11 import java.util.HashMap;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Map;
15
16 import org.dom4j.Attribute;
17 import org.dom4j.Branch;
18 import org.dom4j.CDATA;
19 import org.dom4j.CharacterData;
20 import org.dom4j.Comment;
21 import org.dom4j.Document;
22 import org.dom4j.DocumentType;
23 import org.dom4j.Element;
24 import org.dom4j.Entity;
25 import org.dom4j.Namespace;
26 import org.dom4j.Node;
27 import org.dom4j.ProcessingInstruction;
28 import org.dom4j.Text;
29 import org.dom4j.tree.NamespaceStack;
30
31 import org.xml.sax.Attributes;
32 import org.xml.sax.ContentHandler;
33 import org.xml.sax.DTDHandler;
34 import org.xml.sax.EntityResolver;
35 import org.xml.sax.ErrorHandler;
36 import org.xml.sax.InputSource;
37 import org.xml.sax.SAXException;
38 import org.xml.sax.SAXNotRecognizedException;
39 import org.xml.sax.SAXNotSupportedException;
40 import org.xml.sax.XMLReader;
41 import org.xml.sax.ext.LexicalHandler;
42 import org.xml.sax.helpers.AttributesImpl;
43 import org.xml.sax.helpers.LocatorImpl;
44
45 /***
46 * <p>
47 * <code>SAXWriter</code> writes a DOM4J tree to a SAX ContentHandler.
48 * </p>
49 *
50 * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
51 * @version $Revision: 1.24 $
52 */
53 public class SAXWriter implements XMLReader {
54 protected static final String[] LEXICAL_HANDLER_NAMES = {
55 "http://xml.org/sax/properties/lexical-handler",
56 "http://xml.org/sax/handlers/LexicalHandler" };
57
58 protected static final String FEATURE_NAMESPACE_PREFIXES
59 = "http://xml.org/sax/features/namespace-prefixes";
60
61 protected static final String FEATURE_NAMESPACES
62 = "http://xml.org/sax/features/namespaces";
63
64 /*** <code>ContentHandler</code> to which SAX events are raised */
65 private ContentHandler contentHandler;
66
67 /*** <code>DTDHandler</code> fired when a document has a DTD */
68 private DTDHandler dtdHandler;
69
70 /*** <code>EntityResolver</code> fired when a document has a DTD */
71 private EntityResolver entityResolver;
72
73 private ErrorHandler errorHandler;
74
75 /*** <code>LexicalHandler</code> fired on Entity and CDATA sections */
76 private LexicalHandler lexicalHandler;
77
78 /*** <code>AttributesImpl</code> used when generating the Attributes */
79 private AttributesImpl attributes = new AttributesImpl();
80
81 /*** Stores the features */
82 private Map features = new HashMap();
83
84 /*** Stores the properties */
85 private Map properties = new HashMap();
86
87 /*** Whether namespace declarations are exported as attributes or not */
88 private boolean declareNamespaceAttributes;
89
90 public SAXWriter() {
91 properties.put(FEATURE_NAMESPACE_PREFIXES, Boolean.FALSE);
92 properties.put(FEATURE_NAMESPACE_PREFIXES, Boolean.TRUE);
93 }
94
95 public SAXWriter(ContentHandler contentHandler) {
96 this();
97 this.contentHandler = contentHandler;
98 }
99
100 public SAXWriter(ContentHandler contentHandler,
101 LexicalHandler lexicalHandler) {
102 this();
103 this.contentHandler = contentHandler;
104 this.lexicalHandler = lexicalHandler;
105 }
106
107 public SAXWriter(ContentHandler contentHandler,
108 LexicalHandler lexicalHandler, EntityResolver entityResolver) {
109 this();
110 this.contentHandler = contentHandler;
111 this.lexicalHandler = lexicalHandler;
112 this.entityResolver = entityResolver;
113 }
114
115 /***
116 * A polymorphic method to write any Node to this SAX stream
117 *
118 * @param node
119 * DOCUMENT ME!
120 *
121 * @throws SAXException
122 * DOCUMENT ME!
123 */
124 public void write(Node node) throws SAXException {
125 int nodeType = node.getNodeType();
126
127 switch (nodeType) {
128 case Node.ELEMENT_NODE:
129 write((Element) node);
130
131 break;
132
133 case Node.ATTRIBUTE_NODE:
134 write((Attribute) node);
135
136 break;
137
138 case Node.TEXT_NODE:
139 write(node.getText());
140
141 break;
142
143 case Node.CDATA_SECTION_NODE:
144 write((CDATA) node);
145
146 break;
147
148 case Node.ENTITY_REFERENCE_NODE:
149 write((Entity) node);
150
151 break;
152
153 case Node.PROCESSING_INSTRUCTION_NODE:
154 write((ProcessingInstruction) node);
155
156 break;
157
158 case Node.COMMENT_NODE:
159 write((Comment) node);
160
161 break;
162
163 case Node.DOCUMENT_NODE:
164 write((Document) node);
165
166 break;
167
168 case Node.DOCUMENT_TYPE_NODE:
169 write((DocumentType) node);
170
171 break;
172
173 case Node.NAMESPACE_NODE:
174
175
176
177 break;
178
179 default:
180 throw new SAXException("Invalid node type: " + node);
181 }
182 }
183
184 /***
185 * Generates SAX events for the given Document and all its content
186 *
187 * @param document
188 * is the Document to parse
189 *
190 * @throws SAXException
191 * if there is a SAX error processing the events
192 */
193 public void write(Document document) throws SAXException {
194 if (document != null) {
195 checkForNullHandlers();
196
197 documentLocator(document);
198 startDocument();
199 entityResolver(document);
200 dtdHandler(document);
201
202 writeContent(document, new NamespaceStack());
203 endDocument();
204 }
205 }
206
207 /***
208 * Generates SAX events for the given Element and all its content
209 *
210 * @param element
211 * is the Element to parse
212 *
213 * @throws SAXException
214 * if there is a SAX error processing the events
215 */
216 public void write(Element element) throws SAXException {
217 write(element, new NamespaceStack());
218 }
219
220 /***
221 * <p>
222 * Writes the opening tag of an {@link Element}, including its {@link
223 * Attribute}s but without its content.
224 * </p>
225 *
226 * @param element
227 * <code>Element</code> to output.
228 *
229 * @throws SAXException
230 * DOCUMENT ME!
231 */
232 public void writeOpen(Element element) throws SAXException {
233 startElement(element, null);
234 }
235
236 /***
237 * <p>
238 * Writes the closing tag of an {@link Element}
239 * </p>
240 *
241 * @param element
242 * <code>Element</code> to output.
243 *
244 * @throws SAXException
245 * DOCUMENT ME!
246 */
247 public void writeClose(Element element) throws SAXException {
248 endElement(element);
249 }
250
251 /***
252 * Generates SAX events for the given text
253 *
254 * @param text
255 * is the text to send to the SAX ContentHandler
256 *
257 * @throws SAXException
258 * if there is a SAX error processing the events
259 */
260 public void write(String text) throws SAXException {
261 if (text != null) {
262 char[] chars = text.toCharArray();
263 contentHandler.characters(chars, 0, chars.length);
264 }
265 }
266
267 /***
268 * Generates SAX events for the given CDATA
269 *
270 * @param cdata
271 * is the CDATA to parse
272 *
273 * @throws SAXException
274 * if there is a SAX error processing the events
275 */
276 public void write(CDATA cdata) throws SAXException {
277 String text = cdata.getText();
278
279 if (lexicalHandler != null) {
280 lexicalHandler.startCDATA();
281 write(text);
282 lexicalHandler.endCDATA();
283 } else {
284 write(text);
285 }
286 }
287
288 /***
289 * Generates SAX events for the given Comment
290 *
291 * @param comment
292 * is the Comment to parse
293 *
294 * @throws SAXException
295 * if there is a SAX error processing the events
296 */
297 public void write(Comment comment) throws SAXException {
298 if (lexicalHandler != null) {
299 String text = comment.getText();
300 char[] chars = text.toCharArray();
301 lexicalHandler.comment(chars, 0, chars.length);
302 }
303 }
304
305 /***
306 * Generates SAX events for the given Entity
307 *
308 * @param entity
309 * is the Entity to parse
310 *
311 * @throws SAXException
312 * if there is a SAX error processing the events
313 */
314 public void write(Entity entity) throws SAXException {
315 String text = entity.getText();
316
317 if (lexicalHandler != null) {
318 String name = entity.getName();
319 lexicalHandler.startEntity(name);
320 write(text);
321 lexicalHandler.endEntity(name);
322 } else {
323 write(text);
324 }
325 }
326
327 /***
328 * Generates SAX events for the given ProcessingInstruction
329 *
330 * @param pi
331 * is the ProcessingInstruction to parse
332 *
333 * @throws SAXException
334 * if there is a SAX error processing the events
335 */
336 public void write(ProcessingInstruction pi) throws SAXException {
337 String target = pi.getTarget();
338 String text = pi.getText();
339 contentHandler.processingInstruction(target, text);
340 }
341
342 /***
343 * Should namespace declarations be converted to "xmlns" attributes. This
344 * property defaults to <code>false</code> as per the SAX specification.
345 * This property is set via the SAX feature
346 * "http://xml.org/sax/features/namespace-prefixes"
347 *
348 * @return DOCUMENT ME!
349 */
350 public boolean isDeclareNamespaceAttributes() {
351 return declareNamespaceAttributes;
352 }
353
354 /***
355 * Sets whether namespace declarations should be exported as "xmlns"
356 * attributes or not. This property is set from the SAX feature
357 * "http://xml.org/sax/features/namespace-prefixes"
358 *
359 * @param declareNamespaceAttrs
360 * DOCUMENT ME!
361 */
362 public void setDeclareNamespaceAttributes(boolean declareNamespaceAttrs) {
363 this.declareNamespaceAttributes = declareNamespaceAttrs;
364 }
365
366
367
368
369 /***
370 * DOCUMENT ME!
371 *
372 * @return the <code>ContentHandler</code> called when SAX events are
373 * raised
374 */
375 public ContentHandler getContentHandler() {
376 return contentHandler;
377 }
378
379 /***
380 * Sets the <code>ContentHandler</code> called when SAX events are raised
381 *
382 * @param contentHandler
383 * is the <code>ContentHandler</code> called when SAX events
384 * are raised
385 */
386 public void setContentHandler(ContentHandler contentHandler) {
387 this.contentHandler = contentHandler;
388 }
389
390 /***
391 * DOCUMENT ME!
392 *
393 * @return the <code>DTDHandler</code>
394 */
395 public DTDHandler getDTDHandler() {
396 return dtdHandler;
397 }
398
399 /***
400 * Sets the <code>DTDHandler</code>.
401 *
402 * @param handler
403 * DOCUMENT ME!
404 */
405 public void setDTDHandler(DTDHandler handler) {
406 this.dtdHandler = handler;
407 }
408
409 /***
410 * DOCUMENT ME!
411 *
412 * @return the <code>ErrorHandler</code>
413 */
414 public ErrorHandler getErrorHandler() {
415 return errorHandler;
416 }
417
418 /***
419 * Sets the <code>ErrorHandler</code>.
420 *
421 * @param errorHandler
422 * DOCUMENT ME!
423 */
424 public void setErrorHandler(ErrorHandler errorHandler) {
425 this.errorHandler = errorHandler;
426 }
427
428 /***
429 * DOCUMENT ME!
430 *
431 * @return the <code>EntityResolver</code> used when a Document contains a
432 * DTD
433 */
434 public EntityResolver getEntityResolver() {
435 return entityResolver;
436 }
437
438 /***
439 * Sets the <code>EntityResolver</code>.
440 *
441 * @param entityResolver
442 * is the <code>EntityResolver</code>
443 */
444 public void setEntityResolver(EntityResolver entityResolver) {
445 this.entityResolver = entityResolver;
446 }
447
448 /***
449 * DOCUMENT ME!
450 *
451 * @return the <code>LexicalHandler</code> used when a Document contains a
452 * DTD
453 */
454 public LexicalHandler getLexicalHandler() {
455 return lexicalHandler;
456 }
457
458 /***
459 * Sets the <code>LexicalHandler</code>.
460 *
461 * @param lexicalHandler
462 * is the <code>LexicalHandler</code>
463 */
464 public void setLexicalHandler(LexicalHandler lexicalHandler) {
465 this.lexicalHandler = lexicalHandler;
466 }
467
468 /***
469 * Sets the <code>XMLReader</code> used to write SAX events to
470 *
471 * @param xmlReader
472 * is the <code>XMLReader</code>
473 */
474 public void setXMLReader(XMLReader xmlReader) {
475 setContentHandler(xmlReader.getContentHandler());
476 setDTDHandler(xmlReader.getDTDHandler());
477 setEntityResolver(xmlReader.getEntityResolver());
478 setErrorHandler(xmlReader.getErrorHandler());
479 }
480
481 /***
482 * Looks up the value of a feature.
483 *
484 * @param name
485 * DOCUMENT ME!
486 *
487 * @return DOCUMENT ME!
488 *
489 * @throws SAXNotRecognizedException
490 * DOCUMENT ME!
491 * @throws SAXNotSupportedException
492 * DOCUMENT ME!
493 */
494 public boolean getFeature(String name) throws SAXNotRecognizedException,
495 SAXNotSupportedException {
496 Boolean answer = (Boolean) features.get(name);
497
498 return (answer != null) && answer.booleanValue();
499 }
500
501 /***
502 * This implementation does actually use any features but just stores them
503 * for later retrieval
504 *
505 * @param name
506 * DOCUMENT ME!
507 * @param value
508 * DOCUMENT ME!
509 *
510 * @throws SAXNotRecognizedException
511 * DOCUMENT ME!
512 * @throws SAXNotSupportedException
513 * DOCUMENT ME!
514 */
515 public void setFeature(String name, boolean value)
516 throws SAXNotRecognizedException, SAXNotSupportedException {
517 if (FEATURE_NAMESPACE_PREFIXES.equals(name)) {
518 setDeclareNamespaceAttributes(value);
519 } else if (FEATURE_NAMESPACE_PREFIXES.equals(name)) {
520 if (!value) {
521 String msg = "Namespace feature is always supported in dom4j";
522 throw new SAXNotSupportedException(msg);
523 }
524 }
525
526 features.put(name, (value) ? Boolean.TRUE : Boolean.FALSE);
527 }
528
529 /***
530 * Sets the given SAX property
531 *
532 * @param name
533 * DOCUMENT ME!
534 * @param value
535 * DOCUMENT ME!
536 */
537 public void setProperty(String name, Object value) {
538 for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) {
539 if (LEXICAL_HANDLER_NAMES[i].equals(name)) {
540 setLexicalHandler((LexicalHandler) value);
541
542 return;
543 }
544 }
545
546 properties.put(name, value);
547 }
548
549 /***
550 * Gets the given SAX property
551 *
552 * @param name
553 * DOCUMENT ME!
554 *
555 * @return DOCUMENT ME!
556 *
557 * @throws SAXNotRecognizedException
558 * DOCUMENT ME!
559 * @throws SAXNotSupportedException
560 * DOCUMENT ME!
561 */
562 public Object getProperty(String name) throws SAXNotRecognizedException,
563 SAXNotSupportedException {
564 for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) {
565 if (LEXICAL_HANDLER_NAMES[i].equals(name)) {
566 return getLexicalHandler();
567 }
568 }
569
570 return properties.get(name);
571 }
572
573 /***
574 * This method is not supported.
575 *
576 * @param systemId
577 * DOCUMENT ME!
578 *
579 * @throws SAXNotSupportedException
580 * DOCUMENT ME!
581 */
582 public void parse(String systemId) throws SAXNotSupportedException {
583 throw new SAXNotSupportedException("This XMLReader can only accept"
584 + " <dom4j> InputSource objects");
585 }
586
587 /***
588 * Parses an XML document. This method can only accept DocumentInputSource
589 * inputs otherwise a {@link SAXNotSupportedException}exception is thrown.
590 *
591 * @param input
592 * DOCUMENT ME!
593 *
594 * @throws SAXException
595 * DOCUMENT ME!
596 * @throws SAXNotSupportedException
597 * if the input source is not wrapping a dom4j document
598 */
599 public void parse(InputSource input) throws SAXException {
600 if (input instanceof DocumentInputSource) {
601 DocumentInputSource documentInput = (DocumentInputSource) input;
602 Document document = documentInput.getDocument();
603 write(document);
604 } else {
605 throw new SAXNotSupportedException(
606 "This XMLReader can only accept "
607 + "<dom4j> InputSource objects");
608 }
609 }
610
611
612
613 protected void writeContent(Branch branch, NamespaceStack namespaceStack)
614 throws SAXException {
615 for (Iterator iter = branch.nodeIterator(); iter.hasNext();) {
616 Object object = iter.next();
617
618 if (object instanceof Element) {
619 write((Element) object, namespaceStack);
620 } else if (object instanceof CharacterData) {
621 if (object instanceof Text) {
622 Text text = (Text) object;
623 write(text.getText());
624 } else if (object instanceof CDATA) {
625 write((CDATA) object);
626 } else if (object instanceof Comment) {
627 write((Comment) object);
628 } else {
629 throw new SAXException("Invalid Node in DOM4J content: "
630 + object + " of type: " + object.getClass());
631 }
632 } else if (object instanceof String) {
633 write((String) object);
634 } else if (object instanceof Entity) {
635 write((Entity) object);
636 } else if (object instanceof ProcessingInstruction) {
637 write((ProcessingInstruction) object);
638 } else if (object instanceof Namespace) {
639 write((Namespace) object);
640 } else {
641 throw new SAXException("Invalid Node in DOM4J content: "
642 + object);
643 }
644 }
645 }
646
647 /***
648 * The {@link org.xml.sax.Locator}is only really useful when parsing a
649 * textual document as its main purpose is to identify the line and column
650 * number. Since we are processing an in memory tree which will probably
651 * have its line number information removed, we'll just use -1 for the line
652 * and column numbers.
653 *
654 * @param document
655 * DOCUMENT ME!
656 *
657 * @throws SAXException
658 * DOCUMENT ME!
659 */
660 protected void documentLocator(Document document) throws SAXException {
661 LocatorImpl locator = new LocatorImpl();
662
663 String publicID = null;
664 String systemID = null;
665 DocumentType docType = document.getDocType();
666
667 if (docType != null) {
668 publicID = docType.getPublicID();
669 systemID = docType.getSystemID();
670 }
671
672 if (publicID != null) {
673 locator.setPublicId(publicID);
674 }
675
676 if (systemID != null) {
677 locator.setSystemId(systemID);
678 }
679
680 locator.setLineNumber(-1);
681 locator.setColumnNumber(-1);
682
683 contentHandler.setDocumentLocator(locator);
684 }
685
686 protected void entityResolver(Document document) throws SAXException {
687 if (entityResolver != null) {
688 DocumentType docType = document.getDocType();
689
690 if (docType != null) {
691 String publicID = docType.getPublicID();
692 String systemID = docType.getSystemID();
693
694 if ((publicID != null) || (systemID != null)) {
695 try {
696 entityResolver.resolveEntity(publicID, systemID);
697 } catch (IOException e) {
698 throw new SAXException("Could not resolve publicID: "
699 + publicID + " systemID: " + systemID, e);
700 }
701 }
702 }
703 }
704 }
705
706 /***
707 * We do not yet support DTD or XML Schemas so this method does nothing
708 * right now.
709 *
710 * @param document
711 * DOCUMENT ME!
712 *
713 * @throws SAXException
714 * DOCUMENT ME!
715 */
716 protected void dtdHandler(Document document) throws SAXException {
717 }
718
719 protected void startDocument() throws SAXException {
720 contentHandler.startDocument();
721 }
722
723 protected void endDocument() throws SAXException {
724 contentHandler.endDocument();
725 }
726
727 protected void write(Element element, NamespaceStack namespaceStack)
728 throws SAXException {
729 int stackSize = namespaceStack.size();
730 AttributesImpl namespaceAttributes = startPrefixMapping(element,
731 namespaceStack);
732 startElement(element, namespaceAttributes);
733 writeContent(element, namespaceStack);
734 endElement(element);
735 endPrefixMapping(namespaceStack, stackSize);
736 }
737
738 /***
739 * Fires a SAX startPrefixMapping event for all the namespaceStack which
740 * have just come into scope
741 *
742 * @param element
743 * DOCUMENT ME!
744 * @param namespaceStack
745 * DOCUMENT ME!
746 *
747 * @return DOCUMENT ME!
748 *
749 * @throws SAXException
750 * DOCUMENT ME!
751 */
752 protected AttributesImpl startPrefixMapping(Element element,
753 NamespaceStack namespaceStack) throws SAXException {
754 AttributesImpl namespaceAttributes = null;
755
756
757 Namespace elementNamespace = element.getNamespace();
758
759 if ((elementNamespace != null)
760 && !isIgnoreableNamespace(elementNamespace, namespaceStack)) {
761 namespaceStack.push(elementNamespace);
762 contentHandler.startPrefixMapping(elementNamespace.getPrefix(),
763 elementNamespace.getURI());
764 namespaceAttributes = addNamespaceAttribute(namespaceAttributes,
765 elementNamespace);
766 }
767
768 List declaredNamespaces = element.declaredNamespaces();
769
770 for (int i = 0, size = declaredNamespaces.size(); i < size; i++) {
771 Namespace namespace = (Namespace) declaredNamespaces.get(i);
772
773 if (!isIgnoreableNamespace(namespace, namespaceStack)) {
774 namespaceStack.push(namespace);
775 contentHandler.startPrefixMapping(namespace.getPrefix(),
776 namespace.getURI());
777 namespaceAttributes = addNamespaceAttribute(
778 namespaceAttributes, namespace);
779 }
780 }
781
782 return namespaceAttributes;
783 }
784
785 /***
786 * Fires a SAX endPrefixMapping event for all the namespaceStack which have
787 * gone out of scope
788 *
789 * @param stack
790 * DOCUMENT ME!
791 * @param stackSize
792 * DOCUMENT ME!
793 *
794 * @throws SAXException
795 * DOCUMENT ME!
796 */
797 protected void endPrefixMapping(NamespaceStack stack, int stackSize)
798 throws SAXException {
799 while (stack.size() > stackSize) {
800 Namespace namespace = stack.pop();
801
802 if (namespace != null) {
803 contentHandler.endPrefixMapping(namespace.getPrefix());
804 }
805 }
806 }
807
808 protected void startElement(Element element,
809 AttributesImpl namespaceAttributes) throws SAXException {
810 contentHandler.startElement(element.getNamespaceURI(), element
811 .getName(), element.getQualifiedName(), createAttributes(
812 element, namespaceAttributes));
813 }
814
815 protected void endElement(Element element) throws SAXException {
816 contentHandler.endElement(element.getNamespaceURI(), element.getName(),
817 element.getQualifiedName());
818 }
819
820 protected Attributes createAttributes(Element element,
821 Attributes namespaceAttributes) throws SAXException {
822 attributes.clear();
823
824 if (namespaceAttributes != null) {
825 attributes.setAttributes(namespaceAttributes);
826 }
827
828 for (Iterator iter = element.attributeIterator(); iter.hasNext();) {
829 Attribute attribute = (Attribute) iter.next();
830 attributes.addAttribute(attribute.getNamespaceURI(), attribute
831 .getName(), attribute.getQualifiedName(), "CDATA",
832 attribute.getValue());
833 }
834
835 return attributes;
836 }
837
838 /***
839 * If isDelcareNamespaceAttributes() is enabled then this method will add
840 * the given namespace declaration to the supplied attributes object,
841 * creating one if it does not exist.
842 *
843 * @param attrs
844 * DOCUMENT ME!
845 * @param namespace
846 * DOCUMENT ME!
847 *
848 * @return DOCUMENT ME!
849 */
850 protected AttributesImpl addNamespaceAttribute(AttributesImpl attrs,
851 Namespace namespace) {
852 if (declareNamespaceAttributes) {
853 if (attrs == null) {
854 attrs = new AttributesImpl();
855 }
856
857 String prefix = namespace.getPrefix();
858 String qualifiedName = "xmlns";
859
860 if ((prefix != null) && (prefix.length() > 0)) {
861 qualifiedName = "xmlns:" + prefix;
862 }
863
864 String uri = "";
865 String localName = prefix;
866 String type = "CDATA";
867 String value = namespace.getURI();
868
869 attrs.addAttribute(uri, localName, qualifiedName, type, value);
870 }
871
872 return attrs;
873 }
874
875 /***
876 * DOCUMENT ME!
877 *
878 * @param namespace
879 * DOCUMENT ME!
880 * @param namespaceStack
881 * DOCUMENT ME!
882 *
883 * @return true if the given namespace is an ignorable namespace (such as
884 * Namespace.NO_NAMESPACE or Namespace.XML_NAMESPACE) or if the
885 * namespace has already been declared in the current scope
886 */
887 protected boolean isIgnoreableNamespace(Namespace namespace,
888 NamespaceStack namespaceStack) {
889 if (namespace.equals(Namespace.NO_NAMESPACE)
890 || namespace.equals(Namespace.XML_NAMESPACE)) {
891 return true;
892 }
893
894 String uri = namespace.getURI();
895
896 if ((uri == null) || (uri.length() <= 0)) {
897 return true;
898 }
899
900 return namespaceStack.contains(namespace);
901 }
902
903 /***
904 * Ensures non-null content handlers?
905 */
906 protected void checkForNullHandlers() {
907 }
908 }
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945