Source Code Cross Referenced for XMLSerializer.java in  » Portal » uPortal_rel-2-6-1-GA » org » jasig » portal » 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 » Portal » uPortal_rel 2 6 1 GA » org.jasig.portal.serialize 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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