Source Code Cross Referenced for XMLSerializer.java in  » XML » xerces-2_9_1 » org » apache » xml » serialize » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML » xerces 2_9_1 » org.apache.xml.serialize 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        // Sep 14, 2000:
0019:        //  Fixed problem with namespace handling. Contributed by
0020:        //  David Blondeau <blondeau@intalio.com>
0021:        // Sep 14, 2000:
0022:        //  Fixed serializer to report IO exception directly, instead at
0023:        //  the end of document processing.
0024:        //  Reported by Patrick Higgins <phiggins@transzap.com>
0025:        // Aug 21, 2000:
0026:        //  Fixed bug in startDocument not calling prepare.
0027:        //  Reported by Mikael Staldal <d96-mst-ingen-reklam@d.kth.se>
0028:        // Aug 21, 2000:
0029:        //  Added ability to omit DOCTYPE declaration.
0030:        package org.apache.xml.serialize;
0031:
0032:        import java.io.IOException;
0033:        import java.io.OutputStream;
0034:        import java.io.Writer;
0035:        import java.util.Enumeration;
0036:
0037:        import org.apache.xerces.dom.DOMMessageFormatter;
0038:        import org.apache.xerces.util.NamespaceSupport;
0039:        import org.apache.xerces.util.SymbolTable;
0040:        import org.apache.xerces.util.XMLChar;
0041:        import org.apache.xerces.util.XMLSymbols;
0042:        import org.apache.xerces.xni.NamespaceContext;
0043:        import org.w3c.dom.Attr;
0044:        import org.w3c.dom.DOMError;
0045:        import org.w3c.dom.Element;
0046:        import org.w3c.dom.NamedNodeMap;
0047:        import org.w3c.dom.Node;
0048:        import org.w3c.dom.traversal.NodeFilter;
0049:        import org.xml.sax.AttributeList;
0050:        import org.xml.sax.Attributes;
0051:        import org.xml.sax.SAXException;
0052:        import org.xml.sax.helpers.AttributesImpl;
0053:
0054:        /**
0055:         * Implements an XML serializer supporting both DOM and SAX pretty
0056:         * serializing. For usage instructions see {@link Serializer}.
0057:         * <p>
0058:         * If an output stream is used, the encoding is taken from the
0059:         * output format (defaults to <tt>UTF-8</tt>). If a writer is
0060:         * used, make sure the writer uses the same encoding (if applies)
0061:         * as specified in the output format.
0062:         * <p>
0063:         * The serializer supports both DOM and SAX. SAX serializing is done by firing
0064:         * SAX events and using the serializer as a document handler. DOM serializing is done
0065:         * by calling {@link #serialize(Document)} or by using DOM Level 3  
0066:         * {@link org.w3c.dom.ls.LSSerializer} and
0067:         * serializing with {@link org.w3c.dom.ls.LSSerializer#write},
0068:         * {@link org.w3c.dom.ls.LSSerializer#writeToString}.
0069:         * <p>
0070:         * If an I/O exception occurs while serializing, the serializer
0071:         * will not throw an exception directly, but only throw it
0072:         * at the end of serializing (either DOM or SAX's {@link
0073:         * org.xml.sax.DocumentHandler#endDocument}.
0074:         * <p>
0075:         * For elements that are not specified as whitespace preserving,
0076:         * the serializer will potentially break long text lines at space
0077:         * boundaries, indent lines, and serialize elements on separate
0078:         * lines. Line terminators will be regarded as spaces, and
0079:         * spaces at beginning of line will be stripped.
0080:         * 
0081:         * @deprecated This class was deprecated in Xerces 2.9.0. It is recommended 
0082:         * that new applications use the DOM Level 3 LSSerializer or JAXP's Transformation 
0083:         * API for XML (TrAX) for serializing XML. See the Xerces documentation for more 
0084:         * information.
0085:         * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
0086:         * @author <a href="mailto:rahul.srivastava@sun.com">Rahul Srivastava</a>
0087:         * @author Elena Litani IBM
0088:         * @version $Revision: 476047 $ $Date: 2006-11-16 23:27:45 -0500 (Thu, 16 Nov 2006) $
0089:         * @see Serializer
0090:         */
0091:        public class XMLSerializer extends BaseMarkupSerializer {
0092:
0093:            //
0094:            // constants
0095:            //
0096:
0097:            protected static final boolean DEBUG = false;
0098:
0099:            // 
0100:            // data
0101:            //
0102:
0103:            // 
0104:            // DOM Level 3 implementation: variables intialized in DOMSerializerImpl
0105:            // 
0106:
0107:            /** stores namespaces in scope */
0108:            protected NamespaceSupport fNSBinder;
0109:
0110:            /** stores all namespace bindings on the current element */
0111:            protected NamespaceSupport fLocalNSBinder;
0112:
0113:            /** symbol table for serialization */
0114:            protected SymbolTable fSymbolTable;
0115:
0116:            protected final static String PREFIX = "NS";
0117:
0118:            /**
0119:             * Controls whether namespace fixup should be performed during
0120:             * the serialization. 
0121:             * NOTE: if this field is set to true the following 
0122:             * fields need to be initialized: fNSBinder, fLocalNSBinder, fSymbolTable, 
0123:             * XMLSymbols.EMPTY_STRING, fXmlSymbol, fXmlnsSymbol
0124:             */
0125:            protected boolean fNamespaces = false;
0126:
0127:            /**
0128:             * Controls whether namespace prefixes will be printed out during serialization
0129:             */
0130:            protected boolean fNamespacePrefixes = true;
0131:
0132:            private boolean fPreserveSpace;
0133:
0134:            /**
0135:             * Constructs a new serializer. The serializer cannot be used without
0136:             * calling {@link #setOutputCharStream} or {@link #setOutputByteStream}
0137:             * first.
0138:             */
0139:            public XMLSerializer() {
0140:                super (new OutputFormat(Method.XML, null, false));
0141:            }
0142:
0143:            /**
0144:             * Constructs a new serializer. The serializer cannot be used without
0145:             * calling {@link #setOutputCharStream} or {@link #setOutputByteStream}
0146:             * first.
0147:             */
0148:            public XMLSerializer(OutputFormat format) {
0149:                super (format != null ? format : new OutputFormat(Method.XML,
0150:                        null, false));
0151:                _format.setMethod(Method.XML);
0152:            }
0153:
0154:            /**
0155:             * Constructs a new serializer that writes to the specified writer
0156:             * using the specified output format. If <tt>format</tt> is null,
0157:             * will use a default output format.
0158:             *
0159:             * @param writer The writer to use
0160:             * @param format The output format to use, null for the default
0161:             */
0162:            public XMLSerializer(Writer writer, OutputFormat format) {
0163:                super (format != null ? format : new OutputFormat(Method.XML,
0164:                        null, false));
0165:                _format.setMethod(Method.XML);
0166:                setOutputCharStream(writer);
0167:            }
0168:
0169:            /**
0170:             * Constructs a new serializer that writes to the specified output
0171:             * stream using the specified output format. If <tt>format</tt>
0172:             * is null, will use a default output format.
0173:             *
0174:             * @param output The output stream to use
0175:             * @param format The output format to use, null for the default
0176:             */
0177:            public XMLSerializer(OutputStream output, OutputFormat format) {
0178:                super (format != null ? format : new OutputFormat(Method.XML,
0179:                        null, false));
0180:                _format.setMethod(Method.XML);
0181:                setOutputByteStream(output);
0182:            }
0183:
0184:            public void setOutputFormat(OutputFormat format) {
0185:                super .setOutputFormat(format != null ? format
0186:                        : new OutputFormat(Method.XML, null, false));
0187:            }
0188:
0189:            /**
0190:             * This methods turns on namespace fixup algorithm during
0191:             * DOM serialization.
0192:             * @see org.w3c.dom.ls.LSSerializer
0193:             * 
0194:             * @param namespaces
0195:             */
0196:            public void setNamespaces(boolean namespaces) {
0197:                fNamespaces = namespaces;
0198:                if (fNSBinder == null) {
0199:                    fNSBinder = new NamespaceSupport();
0200:                    fLocalNSBinder = new NamespaceSupport();
0201:                    fSymbolTable = new SymbolTable();
0202:                }
0203:            }
0204:
0205:            //-----------------------------------------//
0206:            // SAX content handler serializing methods //
0207:            //-----------------------------------------//
0208:
0209:            public void startElement(String namespaceURI, String localName,
0210:                    String rawName, Attributes attrs) throws SAXException {
0211:                int i;
0212:                boolean preserveSpace;
0213:                ElementState state;
0214:                String name;
0215:                String value;
0216:
0217:                if (DEBUG) {
0218:                    System.out.println("==>startElement(" + namespaceURI + ","
0219:                            + localName + "," + rawName + ")");
0220:                }
0221:
0222:                try {
0223:                    if (_printer == null) {
0224:                        String msg = DOMMessageFormatter.formatMessage(
0225:                                DOMMessageFormatter.SERIALIZER_DOMAIN,
0226:                                "NoWriterSupplied", null);
0227:                        throw new IllegalStateException(msg);
0228:                    }
0229:
0230:                    state = getElementState();
0231:                    if (isDocumentState()) {
0232:                        // If this is the root element handle it differently.
0233:                        // If the first root element in the document, serialize
0234:                        // the document's DOCTYPE. Space preserving defaults
0235:                        // to that of the output format.
0236:                        if (!_started)
0237:                            startDocument((localName == null || localName
0238:                                    .length() == 0) ? rawName : localName);
0239:                    } else {
0240:                        // For any other element, if first in parent, then
0241:                        // close parent's opening tag and use the parnet's
0242:                        // space preserving.
0243:                        if (state.empty)
0244:                            _printer.printText('>');
0245:                        // Must leave CData section first
0246:                        if (state.inCData) {
0247:                            _printer.printText("]]>");
0248:                            state.inCData = false;
0249:                        }
0250:                        // Indent this element on a new line if the first
0251:                        // content of the parent element or immediately
0252:                        // following an element or a comment
0253:                        if (_indenting
0254:                                && !state.preserveSpace
0255:                                && (state.empty || state.afterElement || state.afterComment))
0256:                            _printer.breakLine();
0257:                    }
0258:                    preserveSpace = state.preserveSpace;
0259:
0260:                    //We remove the namespaces from the attributes list so that they will
0261:                    //be in _prefixes
0262:                    attrs = extractNamespaces(attrs);
0263:
0264:                    // Do not change the current element state yet.
0265:                    // This only happens in endElement().
0266:                    if (rawName == null || rawName.length() == 0) {
0267:                        if (localName == null) {
0268:                            String msg = DOMMessageFormatter.formatMessage(
0269:                                    DOMMessageFormatter.SERIALIZER_DOMAIN,
0270:                                    "NoName", null);
0271:                            throw new SAXException(msg);
0272:                        }
0273:                        if (namespaceURI != null && !namespaceURI.equals("")) {
0274:                            String prefix;
0275:                            prefix = getPrefix(namespaceURI);
0276:                            if (prefix != null && prefix.length() > 0) {
0277:                                rawName = prefix + ":" + localName;
0278:                            } else {
0279:                                rawName = localName;
0280:                            }
0281:                        } else {
0282:                            rawName = localName;
0283:                        }
0284:                    }
0285:
0286:                    _printer.printText('<');
0287:                    _printer.printText(rawName);
0288:                    _printer.indent();
0289:
0290:                    // For each attribute print it's name and value as one part,
0291:                    // separated with a space so the element can be broken on
0292:                    // multiple lines.
0293:                    if (attrs != null) {
0294:                        for (i = 0; i < attrs.getLength(); ++i) {
0295:                            _printer.printSpace();
0296:
0297:                            name = attrs.getQName(i);
0298:                            if (name != null && name.length() == 0) {
0299:                                String prefix;
0300:                                String attrURI;
0301:
0302:                                name = attrs.getLocalName(i);
0303:                                attrURI = attrs.getURI(i);
0304:                                if ((attrURI != null && attrURI.length() != 0)
0305:                                        && (namespaceURI == null
0306:                                                || namespaceURI.length() == 0 || !attrURI
0307:                                                .equals(namespaceURI))) {
0308:                                    prefix = getPrefix(attrURI);
0309:                                    if (prefix != null && prefix.length() > 0)
0310:                                        name = prefix + ":" + name;
0311:                                }
0312:                            }
0313:
0314:                            value = attrs.getValue(i);
0315:                            if (value == null)
0316:                                value = "";
0317:                            _printer.printText(name);
0318:                            _printer.printText("=\"");
0319:                            printEscaped(value);
0320:                            _printer.printText('"');
0321:
0322:                            // If the attribute xml:space exists, determine whether
0323:                            // to preserve spaces in this and child nodes based on
0324:                            // its value.
0325:                            if (name.equals("xml:space")) {
0326:                                if (value.equals("preserve"))
0327:                                    preserveSpace = true;
0328:                                else
0329:                                    preserveSpace = _format.getPreserveSpace();
0330:                            }
0331:                        }
0332:                    }
0333:
0334:                    if (_prefixes != null) {
0335:                        Enumeration keys;
0336:
0337:                        keys = _prefixes.keys();
0338:                        while (keys.hasMoreElements()) {
0339:                            _printer.printSpace();
0340:                            value = (String) keys.nextElement();
0341:                            name = (String) _prefixes.get(value);
0342:                            if (name.length() == 0) {
0343:                                _printer.printText("xmlns=\"");
0344:                                printEscaped(value);
0345:                                _printer.printText('"');
0346:                            } else {
0347:                                _printer.printText("xmlns:");
0348:                                _printer.printText(name);
0349:                                _printer.printText("=\"");
0350:                                printEscaped(value);
0351:                                _printer.printText('"');
0352:                            }
0353:                        }
0354:                    }
0355:
0356:                    // Now it's time to enter a new element state
0357:                    // with the tag name and space preserving.
0358:                    // We still do not change the curent element state.
0359:                    state = enterElementState(namespaceURI, localName, rawName,
0360:                            preserveSpace);
0361:                    name = (localName == null || localName.length() == 0) ? rawName
0362:                            : namespaceURI + "^" + localName;
0363:                    state.doCData = _format.isCDataElement(name);
0364:                    state.unescaped = _format.isNonEscapingElement(name);
0365:                } catch (IOException except) {
0366:                    throw new SAXException(except);
0367:                }
0368:            }
0369:
0370:            public void endElement(String namespaceURI, String localName,
0371:                    String rawName) throws SAXException {
0372:                try {
0373:                    endElementIO(namespaceURI, localName, rawName);
0374:                } catch (IOException except) {
0375:                    throw new SAXException(except);
0376:                }
0377:            }
0378:
0379:            public void endElementIO(String namespaceURI, String localName,
0380:                    String rawName) throws IOException {
0381:                ElementState state;
0382:                if (DEBUG) {
0383:                    System.out.println("==>endElement: " + rawName);
0384:                }
0385:                // Works much like content() with additions for closing
0386:                // an element. Note the different checks for the closed
0387:                // element's state and the parent element's state.
0388:                _printer.unindent();
0389:                state = getElementState();
0390:                if (state.empty) {
0391:                    _printer.printText("/>");
0392:                } else {
0393:                    // Must leave CData section first
0394:                    if (state.inCData)
0395:                        _printer.printText("]]>");
0396:                    // This element is not empty and that last content was
0397:                    // another element, so print a line break before that
0398:                    // last element and this element's closing tag.
0399:                    if (_indenting && !state.preserveSpace
0400:                            && (state.afterElement || state.afterComment))
0401:                        _printer.breakLine();
0402:                    _printer.printText("</");
0403:                    _printer.printText(state.rawName);
0404:                    _printer.printText('>');
0405:                }
0406:                // Leave the element state and update that of the parent
0407:                // (if we're not root) to not empty and after element.
0408:                state = leaveElementState();
0409:                state.afterElement = true;
0410:                state.afterComment = false;
0411:                state.empty = false;
0412:                if (isDocumentState())
0413:                    _printer.flush();
0414:            }
0415:
0416:            //------------------------------------------//
0417:            // SAX document handler serializing methods //
0418:            //------------------------------------------//
0419:
0420:            public void startElement(String tagName, AttributeList attrs)
0421:                    throws SAXException {
0422:                int i;
0423:                boolean preserveSpace;
0424:                ElementState state;
0425:                String name;
0426:                String value;
0427:
0428:                if (DEBUG) {
0429:                    System.out.println("==>startElement(" + tagName + ")");
0430:                }
0431:
0432:                try {
0433:                    if (_printer == null) {
0434:                        String msg = DOMMessageFormatter.formatMessage(
0435:                                DOMMessageFormatter.SERIALIZER_DOMAIN,
0436:                                "NoWriterSupplied", null);
0437:                        throw new IllegalStateException(msg);
0438:                    }
0439:
0440:                    state = getElementState();
0441:                    if (isDocumentState()) {
0442:                        // If this is the root element handle it differently.
0443:                        // If the first root element in the document, serialize
0444:                        // the document's DOCTYPE. Space preserving defaults
0445:                        // to that of the output format.
0446:                        if (!_started)
0447:                            startDocument(tagName);
0448:                    } else {
0449:                        // For any other element, if first in parent, then
0450:                        // close parent's opening tag and use the parnet's
0451:                        // space preserving.
0452:                        if (state.empty)
0453:                            _printer.printText('>');
0454:                        // Must leave CData section first
0455:                        if (state.inCData) {
0456:                            _printer.printText("]]>");
0457:                            state.inCData = false;
0458:                        }
0459:                        // Indent this element on a new line if the first
0460:                        // content of the parent element or immediately
0461:                        // following an element.
0462:                        if (_indenting
0463:                                && !state.preserveSpace
0464:                                && (state.empty || state.afterElement || state.afterComment))
0465:                            _printer.breakLine();
0466:                    }
0467:                    preserveSpace = state.preserveSpace;
0468:
0469:                    // Do not change the current element state yet.
0470:                    // This only happens in endElement().
0471:
0472:                    _printer.printText('<');
0473:                    _printer.printText(tagName);
0474:                    _printer.indent();
0475:
0476:                    // For each attribute print it's name and value as one part,
0477:                    // separated with a space so the element can be broken on
0478:                    // multiple lines.
0479:                    if (attrs != null) {
0480:                        for (i = 0; i < attrs.getLength(); ++i) {
0481:                            _printer.printSpace();
0482:                            name = attrs.getName(i);
0483:                            value = attrs.getValue(i);
0484:                            if (value != null) {
0485:                                _printer.printText(name);
0486:                                _printer.printText("=\"");
0487:                                printEscaped(value);
0488:                                _printer.printText('"');
0489:                            }
0490:
0491:                            // If the attribute xml:space exists, determine whether
0492:                            // to preserve spaces in this and child nodes based on
0493:                            // its value.
0494:                            if (name.equals("xml:space")) {
0495:                                if (value.equals("preserve"))
0496:                                    preserveSpace = true;
0497:                                else
0498:                                    preserveSpace = _format.getPreserveSpace();
0499:                            }
0500:                        }
0501:                    }
0502:                    // Now it's time to enter a new element state
0503:                    // with the tag name and space preserving.
0504:                    // We still do not change the curent element state.
0505:                    state = enterElementState(null, null, tagName,
0506:                            preserveSpace);
0507:                    state.doCData = _format.isCDataElement(tagName);
0508:                    state.unescaped = _format.isNonEscapingElement(tagName);
0509:                } catch (IOException except) {
0510:                    throw new SAXException(except);
0511:                }
0512:
0513:            }
0514:
0515:            public void endElement(String tagName) throws SAXException {
0516:                endElement(null, null, tagName);
0517:            }
0518:
0519:            //------------------------------------------//
0520:            // Generic node serializing methods methods //
0521:            //------------------------------------------//
0522:
0523:            /**
0524:             * Called to serialize the document's DOCTYPE by the root element.
0525:             * The document type declaration must name the root element,
0526:             * but the root element is only known when that element is serialized,
0527:             * and not at the start of the document.
0528:             * <p>
0529:             * This method will check if it has not been called before ({@link #_started}),
0530:             * will serialize the document type declaration, and will serialize all
0531:             * pre-root comments and PIs that were accumulated in the document
0532:             * (see {@link #serializePreRoot}). Pre-root will be serialized even if
0533:             * this is not the first root element of the document.
0534:             */
0535:            protected void startDocument(String rootTagName) throws IOException {
0536:                int i;
0537:                String dtd;
0538:
0539:                dtd = _printer.leaveDTD();
0540:                if (!_started) {
0541:
0542:                    if (!_format.getOmitXMLDeclaration()) {
0543:                        StringBuffer buffer;
0544:
0545:                        // Serialize the document declaration appreaing at the head
0546:                        // of very XML document (unless asked not to).
0547:                        buffer = new StringBuffer("<?xml version=\"");
0548:                        if (_format.getVersion() != null)
0549:                            buffer.append(_format.getVersion());
0550:                        else
0551:                            buffer.append("1.0");
0552:                        buffer.append('"');
0553:                        String format_encoding = _format.getEncoding();
0554:                        if (format_encoding != null) {
0555:                            buffer.append(" encoding=\"");
0556:                            buffer.append(format_encoding);
0557:                            buffer.append('"');
0558:                        }
0559:                        if (_format.getStandalone() && _docTypeSystemId == null
0560:                                && _docTypePublicId == null)
0561:                            buffer.append(" standalone=\"yes\"");
0562:                        buffer.append("?>");
0563:                        _printer.printText(buffer);
0564:                        _printer.breakLine();
0565:                    }
0566:
0567:                    if (!_format.getOmitDocumentType()) {
0568:                        if (_docTypeSystemId != null) {
0569:                            // System identifier must be specified to print DOCTYPE.
0570:                            // If public identifier is specified print 'PUBLIC
0571:                            // <public> <system>', if not, print 'SYSTEM <system>'.
0572:                            _printer.printText("<!DOCTYPE ");
0573:                            _printer.printText(rootTagName);
0574:                            if (_docTypePublicId != null) {
0575:                                _printer.printText(" PUBLIC ");
0576:                                printDoctypeURL(_docTypePublicId);
0577:                                if (_indenting) {
0578:                                    _printer.breakLine();
0579:                                    for (i = 0; i < 18 + rootTagName.length(); ++i)
0580:                                        _printer.printText(" ");
0581:                                } else
0582:                                    _printer.printText(" ");
0583:                                printDoctypeURL(_docTypeSystemId);
0584:                            } else {
0585:                                _printer.printText(" SYSTEM ");
0586:                                printDoctypeURL(_docTypeSystemId);
0587:                            }
0588:
0589:                            // If we accumulated any DTD contents while printing.
0590:                            // this would be the place to print it.
0591:                            if (dtd != null && dtd.length() > 0) {
0592:                                _printer.printText(" [");
0593:                                printText(dtd, true, true);
0594:                                _printer.printText(']');
0595:                            }
0596:
0597:                            _printer.printText(">");
0598:                            _printer.breakLine();
0599:                        } else if (dtd != null && dtd.length() > 0) {
0600:                            _printer.printText("<!DOCTYPE ");
0601:                            _printer.printText(rootTagName);
0602:                            _printer.printText(" [");
0603:                            printText(dtd, true, true);
0604:                            _printer.printText("]>");
0605:                            _printer.breakLine();
0606:                        }
0607:                    }
0608:                }
0609:                _started = true;
0610:                // Always serialize these, even if not te first root element.
0611:                serializePreRoot();
0612:            }
0613:
0614:            /**
0615:             * Called to serialize a DOM element. Equivalent to calling {@link
0616:             * #startElement}, {@link #endElement} and serializing everything
0617:             * inbetween, but better optimized.
0618:             */
0619:            protected void serializeElement(Element elem) throws IOException {
0620:                Attr attr;
0621:                NamedNodeMap attrMap;
0622:                int i;
0623:                Node child;
0624:                ElementState state;
0625:                String name;
0626:                String value;
0627:                String tagName;
0628:
0629:                String prefix, localUri;
0630:                String uri;
0631:                if (fNamespaces) {
0632:                    // local binder stores namespace declaration
0633:                    // that has been printed out during namespace fixup of
0634:                    // the current element
0635:                    fLocalNSBinder.reset();
0636:
0637:                    // add new namespace context        
0638:                    fNSBinder.pushContext();
0639:                }
0640:
0641:                if (DEBUG) {
0642:                    System.out.println("==>startElement: " + elem.getNodeName()
0643:                            + " ns=" + elem.getNamespaceURI());
0644:                }
0645:                tagName = elem.getTagName();
0646:                state = getElementState();
0647:                if (isDocumentState()) {
0648:                    // If this is the root element handle it differently.
0649:                    // If the first root element in the document, serialize
0650:                    // the document's DOCTYPE. Space preserving defaults
0651:                    // to that of the output format.
0652:
0653:                    if (!_started) {
0654:                        startDocument(tagName);
0655:                    }
0656:                } else {
0657:                    // For any other element, if first in parent, then
0658:                    // close parent's opening tag and use the parent's
0659:                    // space preserving.
0660:                    if (state.empty)
0661:                        _printer.printText('>');
0662:                    // Must leave CData section first
0663:                    if (state.inCData) {
0664:                        _printer.printText("]]>");
0665:                        state.inCData = false;
0666:                    }
0667:                    // Indent this element on a new line if the first
0668:                    // content of the parent element or immediately
0669:                    // following an element.
0670:                    if (_indenting
0671:                            && !state.preserveSpace
0672:                            && (state.empty || state.afterElement || state.afterComment))
0673:                        _printer.breakLine();
0674:                }
0675:
0676:                // Do not change the current element state yet.
0677:                // This only happens in endElement().
0678:                fPreserveSpace = state.preserveSpace;
0679:
0680:                int length = 0;
0681:                attrMap = null;
0682:                // retrieve attributes 
0683:                if (elem.hasAttributes()) {
0684:                    attrMap = elem.getAttributes();
0685:                    length = attrMap.getLength();
0686:                }
0687:
0688:                if (!fNamespaces) { // no namespace fixup should be performed                    
0689:
0690:                    // serialize element name
0691:                    _printer.printText('<');
0692:                    _printer.printText(tagName);
0693:                    _printer.indent();
0694:
0695:                    // For each attribute print it's name and value as one part,
0696:                    // separated with a space so the element can be broken on
0697:                    // multiple lines.
0698:                    for (i = 0; i < length; ++i) {
0699:                        attr = (Attr) attrMap.item(i);
0700:                        name = attr.getName();
0701:                        value = attr.getValue();
0702:                        if (value == null)
0703:                            value = "";
0704:                        printAttribute(name, value, attr.getSpecified(), attr);
0705:                    }
0706:                } else { // do namespace fixup
0707:
0708:                    // REVISIT: some optimization could probably be done to avoid traversing 
0709:                    //          attributes twice.
0710:                    //
0711:
0712:                    // ---------------------------------------
0713:                    // record all valid namespace declarations
0714:                    // before attempting to fix element's namespace
0715:                    // ---------------------------------------
0716:
0717:                    for (i = 0; i < length; i++) {
0718:
0719:                        attr = (Attr) attrMap.item(i);
0720:                        uri = attr.getNamespaceURI();
0721:                        // check if attribute is a namespace decl 
0722:                        if (uri != null
0723:                                && uri.equals(NamespaceContext.XMLNS_URI)) {
0724:
0725:                            value = attr.getNodeValue();
0726:                            if (value == null) {
0727:                                value = XMLSymbols.EMPTY_STRING;
0728:                            }
0729:
0730:                            if (value.equals(NamespaceContext.XMLNS_URI)) {
0731:                                if (fDOMErrorHandler != null) {
0732:                                    String msg = DOMMessageFormatter
0733:                                            .formatMessage(
0734:                                                    DOMMessageFormatter.XML_DOMAIN,
0735:                                                    "CantBindXMLNS", null);
0736:                                    modifyDOMError(msg,
0737:                                            DOMError.SEVERITY_ERROR, null, attr);
0738:                                    boolean continueProcess = fDOMErrorHandler
0739:                                            .handleError(fDOMError);
0740:                                    if (!continueProcess) {
0741:                                        // stop the namespace fixup and validation
0742:                                        throw new RuntimeException(
0743:                                                DOMMessageFormatter
0744:                                                        .formatMessage(
0745:                                                                DOMMessageFormatter.SERIALIZER_DOMAIN,
0746:                                                                "SerializationStopped",
0747:                                                                null));
0748:                                    }
0749:                                }
0750:                            } else {
0751:                                prefix = attr.getPrefix();
0752:                                prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING
0753:                                        : fSymbolTable.addSymbol(prefix);
0754:                                String localpart = fSymbolTable.addSymbol(attr
0755:                                        .getLocalName());
0756:                                if (prefix == XMLSymbols.PREFIX_XMLNS) { //xmlns:prefix
0757:                                    value = fSymbolTable.addSymbol(value);
0758:                                    // record valid decl
0759:                                    if (value.length() != 0) {
0760:                                        fNSBinder.declarePrefix(localpart,
0761:                                                value);
0762:                                    } else {
0763:                                        // REVISIT: issue error on invalid declarations
0764:                                        //          xmlns:foo = ""
0765:                                    }
0766:                                    continue;
0767:                                }
0768:                                // xmlns --- empty prefix is always bound ("" or some string)
0769:                                value = fSymbolTable.addSymbol(value);
0770:                                fNSBinder.declarePrefix(
0771:                                        XMLSymbols.EMPTY_STRING, value);
0772:                                continue;
0773:                            } // end-else: valid declaration
0774:                        } // end-if: namespace declaration 
0775:                    } // end-for
0776:
0777:                    //-----------------------
0778:                    // get element uri/prefix
0779:                    //-----------------------
0780:                    uri = elem.getNamespaceURI();
0781:                    prefix = elem.getPrefix();
0782:
0783:                    //----------------------
0784:                    // output element name
0785:                    //----------------------
0786:                    // REVISIT: this could be removed if we always convert empty string to null
0787:                    //          for the namespaces.
0788:                    if ((uri != null && prefix != null) && uri.length() == 0
0789:                            && prefix.length() != 0) {
0790:                        // uri is an empty string and element has some prefix
0791:                        // the namespace alg later will fix up the namespace attributes
0792:                        // remove element prefix 
0793:                        prefix = null;
0794:                        _printer.printText('<');
0795:                        _printer.printText(elem.getLocalName());
0796:                        _printer.indent();
0797:                    } else {
0798:                        _printer.printText('<');
0799:                        _printer.printText(tagName);
0800:                        _printer.indent();
0801:                    }
0802:
0803:                    // ---------------------------------------------------------
0804:                    // Fix up namespaces for element: per DOM L3 
0805:                    // Need to consider the following cases:
0806:                    //
0807:                    // case 1: <foo:elem xmlns:ns1="myURI" xmlns="default"/> 
0808:                    // Assume "foo", "ns1" are declared on the parent. We should not miss 
0809:                    // redeclaration for both "ns1" and default namespace. To solve this 
0810:                    // we add a local binder that stores declaration only for current element.
0811:                    // This way we avoid outputing duplicate declarations for the same element
0812:                    // as well as we are not omitting redeclarations.
0813:                    //
0814:                    // case 2: <elem xmlns="" xmlns="default"/> 
0815:                    // We need to bind default namespace to empty string, to be able to 
0816:                    // omit duplicate declarations for the same element
0817:                    //
0818:                    // case 3: <xsl:stylesheet xmlns:xsl="http://xsl">
0819:                    // We create another element body bound to the "http://xsl" namespace
0820:                    // as well as namespace attribute rebounding xsl to another namespace.
0821:                    // <xsl:body xmlns:xsl="http://another">
0822:                    // Need to make sure that the new namespace decl value is changed to 
0823:                    // "http://xsl"
0824:                    //
0825:                    // ---------------------------------------------------------
0826:                    // check if prefix/namespace is correct for current element
0827:                    // ---------------------------------------------------------
0828:
0829:                    if (uri != null) { // Element has a namespace
0830:                        uri = fSymbolTable.addSymbol(uri);
0831:                        prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING
0832:                                : fSymbolTable.addSymbol(prefix);
0833:                        if (fNSBinder.getURI(prefix) == uri) {
0834:                            // The xmlns:prefix=namespace or xmlns="default" was declared at parent.
0835:                            // The binder always stores mapping of empty prefix to "".
0836:                            // (NOTE: local binder does not store this kind of binding!)
0837:                            // Thus the case where element was declared with uri="" (with or without a prefix)
0838:                            // will be covered here.
0839:
0840:                        } else {
0841:                            // the prefix is either undeclared 
0842:                            // or
0843:                            // conflict: the prefix is bound to another URI
0844:                            if (fNamespacePrefixes) {
0845:                                printNamespaceAttr(prefix, uri);
0846:                            }
0847:                            fLocalNSBinder.declarePrefix(prefix, uri);
0848:                            fNSBinder.declarePrefix(prefix, uri);
0849:                        }
0850:                    } else { // Element has no namespace
0851:                        if (elem.getLocalName() == null) {
0852:                            //  DOM Level 1 node!
0853:                            if (fDOMErrorHandler != null) {
0854:                                String msg = DOMMessageFormatter.formatMessage(
0855:                                        DOMMessageFormatter.DOM_DOMAIN,
0856:                                        "NullLocalElementName",
0857:                                        new Object[] { elem.getNodeName() });
0858:                                modifyDOMError(msg, DOMError.SEVERITY_ERROR,
0859:                                        null, elem);
0860:                                boolean continueProcess = fDOMErrorHandler
0861:                                        .handleError(fDOMError);
0862:                                // REVISIT: should we terminate upon request?
0863:                                if (!continueProcess) {
0864:                                    throw new RuntimeException(
0865:                                            DOMMessageFormatter
0866:                                                    .formatMessage(
0867:                                                            DOMMessageFormatter.SERIALIZER_DOMAIN,
0868:                                                            "SerializationStopped",
0869:                                                            null));
0870:                                }
0871:                            }
0872:                        } else { // uri=null and no colon (DOM L2 node)
0873:                            uri = fNSBinder.getURI(XMLSymbols.EMPTY_STRING);
0874:
0875:                            if (uri != null && uri.length() > 0) {
0876:                                // there is a default namespace decl that is bound to
0877:                                // non-zero length uri, output xmlns=""
0878:                                if (fNamespacePrefixes) {
0879:                                    printNamespaceAttr(XMLSymbols.EMPTY_STRING,
0880:                                            XMLSymbols.EMPTY_STRING);
0881:                                }
0882:                                fLocalNSBinder.declarePrefix(
0883:                                        XMLSymbols.EMPTY_STRING,
0884:                                        XMLSymbols.EMPTY_STRING);
0885:                                fNSBinder.declarePrefix(
0886:                                        XMLSymbols.EMPTY_STRING,
0887:                                        XMLSymbols.EMPTY_STRING);
0888:                            }
0889:                        }
0890:                    }
0891:
0892:                    // -----------------------------------------
0893:                    // Fix up namespaces for attributes: per DOM L3 
0894:                    // check if prefix/namespace is correct the attributes
0895:                    // -----------------------------------------
0896:
0897:                    for (i = 0; i < length; i++) {
0898:
0899:                        attr = (Attr) attrMap.item(i);
0900:                        value = attr.getValue();
0901:                        name = attr.getNodeName();
0902:
0903:                        uri = attr.getNamespaceURI();
0904:
0905:                        // Fix attribute that was declared with a prefix and namespace=""
0906:                        if (uri != null && uri.length() == 0) {
0907:                            uri = null;
0908:                            // we must remove prefix for this attribute
0909:                            name = attr.getLocalName();
0910:                        }
0911:
0912:                        if (DEBUG) {
0913:                            System.out.println("==>process attribute: "
0914:                                    + attr.getNodeName());
0915:                        }
0916:                        // make sure that value is never null.
0917:                        if (value == null) {
0918:                            value = XMLSymbols.EMPTY_STRING;
0919:                        }
0920:
0921:                        if (uri != null) { // attribute has namespace !=null
0922:                            prefix = attr.getPrefix();
0923:                            prefix = prefix == null ? XMLSymbols.EMPTY_STRING
0924:                                    : fSymbolTable.addSymbol(prefix);
0925:                            String localpart = fSymbolTable.addSymbol(attr
0926:                                    .getLocalName());
0927:
0928:                            // ---------------------------------------------------
0929:                            // print namespace declarations namespace declarations 
0930:                            // ---------------------------------------------------
0931:                            if (uri != null
0932:                                    && uri.equals(NamespaceContext.XMLNS_URI)) {
0933:                                // check if we need to output this declaration
0934:                                prefix = attr.getPrefix();
0935:                                prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING
0936:                                        : fSymbolTable.addSymbol(prefix);
0937:                                localpart = fSymbolTable.addSymbol(attr
0938:                                        .getLocalName());
0939:                                if (prefix == XMLSymbols.PREFIX_XMLNS) { //xmlns:prefix
0940:                                    localUri = fLocalNSBinder.getURI(localpart); // local prefix mapping
0941:                                    value = fSymbolTable.addSymbol(value);
0942:                                    if (value.length() != 0) {
0943:                                        if (localUri == null) {
0944:                                            // declaration was not printed while fixing element namespace binding
0945:
0946:                                            // If the DOM Level 3 namespace-prefixes feature is set to false
0947:                                            // do not print xmlns attributes
0948:                                            if (fNamespacePrefixes) {
0949:                                                printNamespaceAttr(localpart,
0950:                                                        value);
0951:                                            }
0952:
0953:                                            // case 4: <elem xmlns:xx="foo" xx:attr=""/>
0954:                                            // where attribute is bound to "bar". 
0955:                                            // If the xmlns:xx is output here first, later we should not
0956:                                            // redeclare "xx" prefix. Instead we would pick up different prefix
0957:                                            // for the attribute.
0958:                                            // final: <elem xmlns:xx="foo" NS1:attr="" xmlns:NS1="bar"/>
0959:                                            fLocalNSBinder.declarePrefix(
0960:                                                    localpart, value);
0961:                                        }
0962:                                    } else {
0963:                                        // REVISIT: issue error on invalid declarations
0964:                                        //          xmlns:foo = ""
0965:                                    }
0966:                                    continue;
0967:                                }
0968:                                // xmlns --- empty prefix is always bound ("" or some string)
0969:                                uri = fNSBinder.getURI(XMLSymbols.EMPTY_STRING);
0970:                                localUri = fLocalNSBinder
0971:                                        .getURI(XMLSymbols.EMPTY_STRING);
0972:                                value = fSymbolTable.addSymbol(value);
0973:                                if (localUri == null) {
0974:                                    // declaration was not printed while fixing element namespace binding
0975:                                    if (fNamespacePrefixes) {
0976:                                        printNamespaceAttr(
0977:                                                XMLSymbols.EMPTY_STRING, value);
0978:                                    }
0979:                                    // case 4 does not apply here since attributes can't use
0980:                                    // default namespace
0981:                                }
0982:                                continue;
0983:
0984:                            }
0985:                            uri = fSymbolTable.addSymbol(uri);
0986:
0987:                            // find if for this prefix a URI was already declared
0988:                            String declaredURI = fNSBinder.getURI(prefix);
0989:
0990:                            if (prefix == XMLSymbols.EMPTY_STRING
0991:                                    || declaredURI != uri) {
0992:                                // attribute has no prefix (default namespace decl does not apply to attributes) 
0993:                                // OR
0994:                                // attribute prefix is not declared
0995:                                // OR
0996:                                // conflict: attr URI does not match the prefix in scope
0997:
0998:                                name = attr.getNodeName();
0999:                                // Find if any prefix for attributes namespace URI is available
1000:                                // in the scope
1001:                                String declaredPrefix = fNSBinder
1002:                                        .getPrefix(uri);
1003:
1004:                                if (declaredPrefix != null
1005:                                        && declaredPrefix != XMLSymbols.EMPTY_STRING) {
1006:                                    // use the prefix that was found
1007:                                    prefix = declaredPrefix;
1008:                                    name = prefix + ":" + localpart;
1009:                                } else {
1010:                                    if (DEBUG) {
1011:                                        System.out
1012:                                                .println("==> cound not find prefix for the attribute: "
1013:                                                        + prefix);
1014:                                    }
1015:
1016:                                    if (prefix != XMLSymbols.EMPTY_STRING
1017:                                            && fLocalNSBinder.getURI(prefix) == null) {
1018:                                        // the current prefix is not null and it has no in scope declaration
1019:
1020:                                        // use this prefix
1021:                                    } else {
1022:                                        // find a prefix following the pattern "NS" +index (starting at 1)
1023:                                        // make sure this prefix is not declared in the current scope.
1024:                                        int counter = 1;
1025:                                        prefix = fSymbolTable.addSymbol(PREFIX
1026:                                                + counter++);
1027:                                        while (fLocalNSBinder.getURI(prefix) != null) {
1028:                                            prefix = fSymbolTable
1029:                                                    .addSymbol(PREFIX
1030:                                                            + counter++);
1031:                                        }
1032:                                        name = prefix + ":" + localpart;
1033:                                    }
1034:                                    // add declaration for the new prefix
1035:                                    if (fNamespacePrefixes) {
1036:                                        printNamespaceAttr(prefix, uri);
1037:                                    }
1038:                                    value = fSymbolTable.addSymbol(value);
1039:                                    fLocalNSBinder.declarePrefix(prefix, value);
1040:                                    fNSBinder.declarePrefix(prefix, uri);
1041:                                }
1042:
1043:                                // change prefix for this attribute
1044:                            }
1045:
1046:                            printAttribute(name,
1047:                                    (value == null) ? XMLSymbols.EMPTY_STRING
1048:                                            : value, attr.getSpecified(), attr);
1049:                        } else { // attribute uri == null
1050:                            if (attr.getLocalName() == null) {
1051:                                if (fDOMErrorHandler != null) {
1052:                                    String msg = DOMMessageFormatter
1053:                                            .formatMessage(
1054:                                                    DOMMessageFormatter.DOM_DOMAIN,
1055:                                                    "NullLocalAttrName",
1056:                                                    new Object[] { attr
1057:                                                            .getNodeName() });
1058:                                    modifyDOMError(msg,
1059:                                            DOMError.SEVERITY_ERROR, null, attr);
1060:                                    boolean continueProcess = fDOMErrorHandler
1061:                                            .handleError(fDOMError);
1062:                                    if (!continueProcess) {
1063:                                        // stop the namespace fixup and validation
1064:                                        throw new RuntimeException(
1065:                                                DOMMessageFormatter
1066:                                                        .formatMessage(
1067:                                                                DOMMessageFormatter.SERIALIZER_DOMAIN,
1068:                                                                "SerializationStopped",
1069:                                                                null));
1070:                                    }
1071:                                }
1072:                                printAttribute(name, value,
1073:                                        attr.getSpecified(), attr);
1074:                            } else { // uri=null and no colon
1075:
1076:                                // no fix up is needed: default namespace decl does not 
1077:                                // apply to attributes
1078:                                printAttribute(name, value,
1079:                                        attr.getSpecified(), attr);
1080:                            }
1081:                        }
1082:                    } // end loop for attributes
1083:
1084:                }// end namespace fixup algorithm
1085:
1086:                // If element has children, then serialize them, otherwise
1087:                // serialize en empty tag.        
1088:                if (elem.hasChildNodes()) {
1089:                    // Enter an element state, and serialize the children
1090:                    // one by one. Finally, end the element.
1091:                    state = enterElementState(null, null, tagName,
1092:                            fPreserveSpace);
1093:                    state.doCData = _format.isCDataElement(tagName);
1094:                    state.unescaped = _format.isNonEscapingElement(tagName);
1095:                    child = elem.getFirstChild();
1096:                    while (child != null) {
1097:                        serializeNode(child);
1098:                        child = child.getNextSibling();
1099:                    }
1100:                    if (fNamespaces) {
1101:                        fNSBinder.popContext();
1102:                    }
1103:                    endElementIO(null, null, tagName);
1104:                } else {
1105:                    if (DEBUG) {
1106:                        System.out.println("==>endElement: "
1107:                                + elem.getNodeName());
1108:                    }
1109:                    if (fNamespaces) {
1110:                        fNSBinder.popContext();
1111:                    }
1112:                    _printer.unindent();
1113:                    _printer.printText("/>");
1114:                    // After element but parent element is no longer empty.
1115:                    state.afterElement = true;
1116:                    state.afterComment = false;
1117:                    state.empty = false;
1118:                    if (isDocumentState())
1119:                        _printer.flush();
1120:                }
1121:            }
1122:
1123:            /**
1124:             * Serializes a namespace attribute with the given prefix and value for URI.
1125:             * In case prefix is empty will serialize default namespace declaration.
1126:             * 
1127:             * @param prefix
1128:             * @param uri
1129:             * @exception IOException
1130:             */
1131:
1132:            private void printNamespaceAttr(String prefix, String uri)
1133:                    throws IOException {
1134:                _printer.printSpace();
1135:                if (prefix == XMLSymbols.EMPTY_STRING) {
1136:                    if (DEBUG) {
1137:                        System.out.println("=>add xmlns=\"" + uri
1138:                                + "\" declaration");
1139:                    }
1140:                    _printer.printText(XMLSymbols.PREFIX_XMLNS);
1141:                } else {
1142:                    if (DEBUG) {
1143:                        System.out.println("=>add xmlns:" + prefix + "=\""
1144:                                + uri + "\" declaration");
1145:                    }
1146:                    _printer.printText("xmlns:" + prefix);
1147:                }
1148:                _printer.printText("=\"");
1149:                printEscaped(uri);
1150:                _printer.printText('"');
1151:            }
1152:
1153:            /**
1154:             * Prints attribute. 
1155:             * NOTE: xml:space attribute modifies output format
1156:             * 
1157:             * @param name
1158:             * @param value
1159:             * @param isSpecified
1160:             * @exception IOException
1161:             */
1162:            private void printAttribute(String name, String value,
1163:                    boolean isSpecified, Attr attr) throws IOException {
1164:
1165:                if (isSpecified
1166:                        || (features & DOMSerializerImpl.DISCARDDEFAULT) == 0) {
1167:                    if (fDOMFilter != null
1168:                            && (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ATTRIBUTE) != 0) {
1169:                        short code = fDOMFilter.acceptNode(attr);
1170:                        switch (code) {
1171:                        case NodeFilter.FILTER_REJECT:
1172:                        case NodeFilter.FILTER_SKIP: {
1173:                            return;
1174:                        }
1175:                        default: {
1176:                            // fall through
1177:                        }
1178:                        }
1179:                    }
1180:                    _printer.printSpace();
1181:                    _printer.printText(name);
1182:                    _printer.printText("=\"");
1183:                    printEscaped(value);
1184:                    _printer.printText('"');
1185:                }
1186:
1187:                // If the attribute xml:space exists, determine whether
1188:                // to preserve spaces in this and child nodes based on
1189:                // its value.
1190:                if (name.equals("xml:space")) {
1191:                    if (value.equals("preserve"))
1192:                        fPreserveSpace = true;
1193:                    else
1194:                        fPreserveSpace = _format.getPreserveSpace();
1195:                }
1196:            }
1197:
1198:            protected String getEntityRef(int ch) {
1199:                // Encode special XML characters into the equivalent character references.
1200:                // These five are defined by default for all XML documents.
1201:                switch (ch) {
1202:                case '<':
1203:                    return "lt";
1204:                case '>':
1205:                    return "gt";
1206:                case '"':
1207:                    return "quot";
1208:                case '\'':
1209:                    return "apos";
1210:                case '&':
1211:                    return "amp";
1212:                }
1213:                return null;
1214:            }
1215:
1216:            /** Retrieve and remove the namespaces declarations from the list of attributes.
1217:             *
1218:             */
1219:            private Attributes extractNamespaces(Attributes attrs)
1220:                    throws SAXException {
1221:                AttributesImpl attrsOnly;
1222:                String rawName;
1223:                int i;
1224:                int length;
1225:
1226:                if (attrs == null) {
1227:                    return null;
1228:                }
1229:                length = attrs.getLength();
1230:                attrsOnly = new AttributesImpl(attrs);
1231:
1232:                for (i = length - 1; i >= 0; --i) {
1233:                    rawName = attrsOnly.getQName(i);
1234:
1235:                    //We have to exclude the namespaces declarations from the attributes
1236:                    //Append only when the feature http://xml.org/sax/features/namespace-prefixes"
1237:                    //is TRUE
1238:                    if (rawName.startsWith("xmlns")) {
1239:                        if (rawName.length() == 5) {
1240:                            startPrefixMapping("", attrs.getValue(i));
1241:                            attrsOnly.removeAttribute(i);
1242:                        } else if (rawName.charAt(5) == ':') {
1243:                            startPrefixMapping(rawName.substring(6), attrs
1244:                                    .getValue(i));
1245:                            attrsOnly.removeAttribute(i);
1246:                        }
1247:                    }
1248:                }
1249:                return attrsOnly;
1250:            }
1251:
1252:            //
1253:            // Printing attribute value
1254:            //
1255:            protected void printEscaped(String source) throws IOException {
1256:                int length = source.length();
1257:                for (int i = 0; i < length; ++i) {
1258:                    int ch = source.charAt(i);
1259:                    if (!XMLChar.isValid(ch)) {
1260:                        if (++i < length) {
1261:                            surrogates(ch, source.charAt(i), false);
1262:                        } else {
1263:                            fatalError("The character '" + (char) ch
1264:                                    + "' is an invalid XML character");
1265:                        }
1266:                        continue;
1267:                    }
1268:                    // escape NL, CR, TAB
1269:                    if (ch == '\n' || ch == '\r' || ch == '\t') {
1270:                        printHex(ch);
1271:                    } else if (ch == '<') {
1272:                        _printer.printText("&lt;");
1273:                    } else if (ch == '&') {
1274:                        _printer.printText("&amp;");
1275:                    } else if (ch == '"') {
1276:                        _printer.printText("&quot;");
1277:                    } else if ((ch >= ' ' && _encodingInfo
1278:                            .isPrintable((char) ch))) {
1279:                        _printer.printText((char) ch);
1280:                    } else {
1281:                        printHex(ch);
1282:                    }
1283:                }
1284:            }
1285:
1286:            /** print text data */
1287:            protected void printXMLChar(int ch) throws IOException {
1288:                if (ch == '\r') {
1289:                    printHex(ch);
1290:                } else if (ch == '<') {
1291:                    _printer.printText("&lt;");
1292:                } else if (ch == '&') {
1293:                    _printer.printText("&amp;");
1294:                } else if (ch == '>') {
1295:                    // character sequence "]]>" can't appear in content, therefore
1296:                    // we should escape '>' 
1297:                    _printer.printText("&gt;");
1298:                } else if (ch == '\n' || ch == '\t'
1299:                        || (ch >= ' ' && _encodingInfo.isPrintable((char) ch))) {
1300:                    _printer.printText((char) ch);
1301:                } else {
1302:                    printHex(ch);
1303:                }
1304:            }
1305:
1306:            protected void printText(String text, boolean preserveSpace,
1307:                    boolean unescaped) throws IOException {
1308:                int index;
1309:                char ch;
1310:                int length = text.length();
1311:                if (preserveSpace) {
1312:                    // Preserving spaces: the text must print exactly as it is,
1313:                    // without breaking when spaces appear in the text and without
1314:                    // consolidating spaces. If a line terminator is used, a line
1315:                    // break will occur.
1316:                    for (index = 0; index < length; ++index) {
1317:                        ch = text.charAt(index);
1318:                        if (!XMLChar.isValid(ch)) {
1319:                            // check if it is surrogate
1320:                            if (++index < length) {
1321:                                surrogates(ch, text.charAt(index), true);
1322:                            } else {
1323:                                fatalError("The character '" + ch
1324:                                        + "' is an invalid XML character");
1325:                            }
1326:                            continue;
1327:                        }
1328:                        if (unescaped) {
1329:                            _printer.printText(ch);
1330:                        } else
1331:                            printXMLChar(ch);
1332:                    }
1333:                } else {
1334:                    // Not preserving spaces: print one part at a time, and
1335:                    // use spaces between parts to break them into different
1336:                    // lines. Spaces at beginning of line will be stripped
1337:                    // by printing mechanism. Line terminator is treated
1338:                    // no different than other text part.
1339:                    for (index = 0; index < length; ++index) {
1340:                        ch = text.charAt(index);
1341:                        if (!XMLChar.isValid(ch)) {
1342:                            // check if it is surrogate
1343:                            if (++index < length) {
1344:                                surrogates(ch, text.charAt(index), true);
1345:                            } else {
1346:                                fatalError("The character '" + ch
1347:                                        + "' is an invalid XML character");
1348:                            }
1349:                            continue;
1350:                        }
1351:
1352:                        if (unescaped)
1353:                            _printer.printText(ch);
1354:                        else
1355:                            printXMLChar(ch);
1356:                    }
1357:                }
1358:            }
1359:
1360:            protected void printText(char[] chars, int start, int length,
1361:                    boolean preserveSpace, boolean unescaped)
1362:                    throws IOException {
1363:
1364:                if (preserveSpace) {
1365:                    // Preserving spaces: the text must print exactly as it is,
1366:                    // without breaking when spaces appear in the text and without
1367:                    // consolidating spaces. If a line terminator is used, a line
1368:                    // break will occur.
1369:                    while (length-- > 0) {
1370:                        char ch = chars[start++];
1371:                        if (!XMLChar.isValid(ch)) {
1372:                            // check if it is surrogate
1373:                            if (length-- > 0) {
1374:                                surrogates(ch, chars[start++], true);
1375:                            } else {
1376:                                fatalError("The character '" + ch
1377:                                        + "' is an invalid XML character");
1378:                            }
1379:                            continue;
1380:                        }
1381:                        if (unescaped) {
1382:                            _printer.printText(ch);
1383:                        } else {
1384:                            printXMLChar(ch);
1385:                        }
1386:                    }
1387:                } else {
1388:                    // Not preserving spaces: print one part at a time, and
1389:                    // use spaces between parts to break them into different
1390:                    // lines. Spaces at beginning of line will be stripped
1391:                    // by printing mechanism. Line terminator is treated
1392:                    // no different than other text part.
1393:                    while (length-- > 0) {
1394:                        char ch = chars[start++];
1395:                        if (!XMLChar.isValid(ch)) {
1396:                            // check if it is surrogate
1397:                            if (length-- > 0) {
1398:                                surrogates(ch, chars[start++], true);
1399:                            } else {
1400:                                fatalError("The character '" + ch
1401:                                        + "' is an invalid XML character");
1402:                            }
1403:                            continue;
1404:                        }
1405:                        if (unescaped) {
1406:                            _printer.printText(ch);
1407:                        } else {
1408:                            printXMLChar(ch);
1409:                        }
1410:                    }
1411:                }
1412:            }
1413:
1414:            /**
1415:             * DOM Level 3:
1416:             * Check a node to determine if it contains unbound namespace prefixes.
1417:             *
1418:             * @param node The node to check for unbound namespace prefices
1419:             */
1420:            protected void checkUnboundNamespacePrefixedNode(Node node)
1421:                    throws IOException {
1422:
1423:                if (fNamespaces) {
1424:
1425:                    if (DEBUG) {
1426:                        System.out.println("==>serializeNode("
1427:                                + node.getNodeName()
1428:                                + ") [Entity Reference - Namespaces on]");
1429:                        System.out.println("==>Declared Prefix Count: "
1430:                                + fNSBinder.getDeclaredPrefixCount());
1431:                        System.out.println("==>Node Name: "
1432:                                + node.getNodeName());
1433:                        System.out.println("==>First Child Node Name: "
1434:                                + node.getFirstChild().getNodeName());
1435:                        System.out.println("==>First Child Node Prefix: "
1436:                                + node.getFirstChild().getPrefix());
1437:                        System.out.println("==>First Child Node NamespaceURI: "
1438:                                + node.getFirstChild().getNamespaceURI());
1439:                    }
1440:
1441:                    Node child, next;
1442:                    for (child = node.getFirstChild(); child != null; child = next) {
1443:                        next = child.getNextSibling();
1444:                        if (DEBUG) {
1445:                            System.out.println("==>serializeNode("
1446:                                    + child.getNodeName() + ") [Child Node]");
1447:                            System.out.println("==>serializeNode("
1448:                                    + child.getPrefix()
1449:                                    + ") [Child Node Prefix]");
1450:                        }
1451:
1452:                        //If a NamespaceURI is not declared for the current
1453:                        //node's prefix, raise a fatal error.
1454:                        String prefix = child.getPrefix();
1455:                        prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING
1456:                                : fSymbolTable.addSymbol(prefix);
1457:                        if (fNSBinder.getURI(prefix) == null && prefix != null) {
1458:                            fatalError("The replacement text of the entity node '"
1459:                                    + node.getNodeName()
1460:                                    + "' contains an element node '"
1461:                                    + child.getNodeName()
1462:                                    + "' with an undeclared prefix '"
1463:                                    + prefix
1464:                                    + "'.");
1465:                        }
1466:
1467:                        if (child.getNodeType() == Node.ELEMENT_NODE) {
1468:
1469:                            NamedNodeMap attrs = child.getAttributes();
1470:
1471:                            for (int i = 0; i < attrs.getLength(); i++) {
1472:
1473:                                String attrPrefix = attrs.item(i).getPrefix();
1474:                                attrPrefix = (attrPrefix == null || attrPrefix
1475:                                        .length() == 0) ? XMLSymbols.EMPTY_STRING
1476:                                        : fSymbolTable.addSymbol(attrPrefix);
1477:                                if (fNSBinder.getURI(attrPrefix) == null
1478:                                        && attrPrefix != null) {
1479:                                    fatalError("The replacement text of the entity node '"
1480:                                            + node.getNodeName()
1481:                                            + "' contains an element node '"
1482:                                            + child.getNodeName()
1483:                                            + "' with an attribute '"
1484:                                            + attrs.item(i).getNodeName()
1485:                                            + "' an undeclared prefix '"
1486:                                            + attrPrefix + "'.");
1487:                                }
1488:
1489:                            }
1490:
1491:                        }
1492:
1493:                        if (child.hasChildNodes()) {
1494:                            checkUnboundNamespacePrefixedNode(child);
1495:                        }
1496:                    }
1497:                }
1498:            }
1499:
1500:            public boolean reset() {
1501:                super .reset();
1502:                if (fNSBinder != null) {
1503:                    fNSBinder.reset();
1504:                    // during serialization always have a mapping to empty string
1505:                    // so we assume there is a declaration.
1506:                    fNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING,
1507:                            XMLSymbols.EMPTY_STRING);
1508:                }
1509:                return true;
1510:            }
1511:
1512:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.