Source Code Cross Referenced for XmlWriter.java in  » Web-Services » restlet-1.0.8 » org » restlet » util » 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 » Web Services » restlet 1.0.8 » org.restlet.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2005-2007 Noelios Consulting.
0003:         * 
0004:         * The contents of this file are subject to the terms of the Common Development
0005:         * and Distribution License (the "License"). You may not use this file except in
0006:         * compliance with the License.
0007:         * 
0008:         * You can obtain a copy of the license at
0009:         * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
0010:         * language governing permissions and limitations under the License.
0011:         * 
0012:         * When distributing Covered Code, include this CDDL HEADER in each file and
0013:         * include the License file at http://www.opensource.org/licenses/cddl1.txt If
0014:         * applicable, add the following below this CDDL HEADER, with the fields
0015:         * enclosed by brackets "[]" replaced with your own identifying information:
0016:         * Portions Copyright [yyyy] [name of copyright owner]
0017:         */
0018:
0019:        package org.restlet.util;
0020:
0021:        import java.io.IOException;
0022:        import java.io.OutputStream;
0023:        import java.io.OutputStreamWriter;
0024:        import java.io.UnsupportedEncodingException;
0025:        import java.io.Writer;
0026:        import java.nio.charset.Charset;
0027:        import java.nio.charset.CharsetEncoder;
0028:        import java.util.Enumeration;
0029:        import java.util.Map;
0030:        import java.util.Stack;
0031:        import java.util.TreeMap;
0032:
0033:        import org.xml.sax.Attributes;
0034:        import org.xml.sax.SAXException;
0035:        import org.xml.sax.XMLReader;
0036:        import org.xml.sax.helpers.AttributesImpl;
0037:        import org.xml.sax.helpers.NamespaceSupport;
0038:        import org.xml.sax.helpers.XMLFilterImpl;
0039:
0040:        /**
0041:         * XML writer doing the opposite work of a SAX-based XML reader. The
0042:         * implementation is based on the work of David Megginson, the creator of SAX
0043:         * who placed the original code in the public domain.
0044:         * 
0045:         * <p>
0046:         * This class can be used by itself or as part of a SAX event stream: it takes
0047:         * as input a series of SAX2 ContentHandler events and uses the information in
0048:         * those events to write an XML document. Since this class is a filter, it can
0049:         * also pass the events on down a filter chain for further processing (you can
0050:         * use the XmlWriter to take a snapshot of the current state at any point in a
0051:         * filter chain), and it can be used directly as a ContentHandler for a SAX2
0052:         * XMLReader.
0053:         * </p>
0054:         * 
0055:         * <p>
0056:         * The client creates a document by invoking the methods for standard SAX2
0057:         * events, always beginning with the {@link #startDocument startDocument} method
0058:         * and ending with the {@link #endDocument endDocument} method. There are
0059:         * convenience methods provided so that clients to not have to create empty
0060:         * attribute lists or provide empty strings as parameters; for example, the
0061:         * method invocation
0062:         * </p>
0063:         * 
0064:         * <pre>
0065:         * w.startElement(&quot;foo&quot;);
0066:         * </pre>
0067:         * 
0068:         * <p>
0069:         * is equivalent to the regular SAX2 ContentHandler method
0070:         * </p>
0071:         * 
0072:         * <pre>
0073:         * w.startElement(&quot;&quot;, &quot;foo&quot;, &quot;&quot;, new AttributesImpl());
0074:         * </pre>
0075:         * 
0076:         * <p>
0077:         * Except that it is more efficient because it does not allocate a new empty
0078:         * attribute list each time. The following code will send a simple XML document
0079:         * to standard output:
0080:         * </p>
0081:         * 
0082:         * <pre>
0083:         * XmlWriter w = new XmlWriter();
0084:         * 
0085:         * w.startDocument();
0086:         * w.startElement(&quot;greeting&quot;);
0087:         * w.characters(&quot;Hello, world!&quot;);
0088:         * w.endElement(&quot;greeting&quot;);
0089:         * w.endDocument();
0090:         * </pre>
0091:         * 
0092:         * <p>
0093:         * The resulting document will look like this:
0094:         * </p>
0095:         * 
0096:         * <pre>
0097:         *           &lt;?xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt;
0098:         *          
0099:         *           &lt;greeting&gt;Hello, world!&lt;/greeting&gt;
0100:         * </pre>
0101:         * 
0102:         * <p>
0103:         * In fact, there is an even simpler convenience method, <var>dataElement</var>,
0104:         * designed for writing elements that contain only character data, so the code
0105:         * to generate the document could be shortened to
0106:         * </p>
0107:         * 
0108:         * <pre>
0109:         * XmlWriter w = new XmlWriter();
0110:         * 
0111:         * w.startDocument();
0112:         * w.dataElement(&quot;greeting&quot;, &quot;Hello, world!&quot;);
0113:         * w.endDocument();
0114:         * </pre>
0115:         * 
0116:         * <h2>Whitespace</h2>
0117:         * 
0118:         * <p>
0119:         * According to the XML Recommendation, <em>all</em> whitespace in an XML
0120:         * document is potentially significant to an application, so this class never
0121:         * adds newlines or indentation. If you insert three elements in a row, as in
0122:         * </p>
0123:         * 
0124:         * <pre>
0125:         * w.dataElement(&quot;item&quot;, &quot;1&quot;);
0126:         * w.dataElement(&quot;item&quot;, &quot;2&quot;);
0127:         * w.dataElement(&quot;item&quot;, &quot;3&quot;);
0128:         * </pre>
0129:         * 
0130:         * <p>
0131:         * you will end up with
0132:         * </p>
0133:         * 
0134:         * <pre>
0135:         *           &lt;item&gt;1&lt;/item&gt;&lt;item&gt;3&lt;/item&gt;&lt;item&gt;3&lt;/item&gt;
0136:         * </pre>
0137:         * 
0138:         * <p>
0139:         * You need to invoke one of the <var>characters</var> methods explicitly to
0140:         * add newlines or indentation. Alternatively, you can use the data format mode
0141:         * (set the "dataFormat" property) which is optimized for writing purely
0142:         * data-oriented (or field-oriented) XML, and does automatic linebreaks and
0143:         * indentation (but does not support mixed content properly). See details below.
0144:         * </p>
0145:         * 
0146:         * <h2>Namespace Support</h2>
0147:         * 
0148:         * <p>
0149:         * The writer contains extensive support for XML Namespaces, so that a client
0150:         * application does not have to keep track of prefixes and supply <var>xmlns</var>
0151:         * attributes. By default, the XML writer will generate Namespace declarations
0152:         * in the form _NS1, _NS2, etc., wherever they are needed, as in the following
0153:         * example:
0154:         * </p>
0155:         * 
0156:         * <pre>
0157:         * w.startDocument();
0158:         * w.emptyElement(&quot;http://www.foo.com/ns/&quot;, &quot;foo&quot;);
0159:         * w.endDocument();
0160:         * </pre>
0161:         * 
0162:         * <p>
0163:         * The resulting document will look like this:
0164:         * </p>
0165:         * 
0166:         * <pre>
0167:         *           &lt;?xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt;
0168:         *          
0169:         *           &lt;_NS1:foo xmlns:_NS1=&quot;http://www.foo.com/ns/&quot;/&gt;
0170:         * </pre>
0171:         * 
0172:         * <p>
0173:         * In many cases, document authors will prefer to choose their own prefixes
0174:         * rather than using the (ugly) default names. The XML writer allows two methods
0175:         * for selecting prefixes:
0176:         * </p>
0177:         * 
0178:         * <ol>
0179:         * <li>the qualified name</li>
0180:         * <li>the {@link #setPrefix setPrefix} method.</li>
0181:         * </ol>
0182:         * 
0183:         * <p>
0184:         * Whenever the XML writer finds a new Namespace URI, it checks to see if a
0185:         * qualified (prefixed) name is also available; if so it attempts to use the
0186:         * name's prefix (as long as the prefix is not already in use for another
0187:         * Namespace URI).
0188:         * </p>
0189:         * 
0190:         * <p>
0191:         * Before writing a document, the client can also pre-map a prefix to a
0192:         * Namespace URI with the setPrefix method:
0193:         * </p>
0194:         * 
0195:         * <pre>
0196:         * w.setPrefix(&quot;http://www.foo.com/ns/&quot;, &quot;foo&quot;);
0197:         * w.startDocument();
0198:         * w.emptyElement(&quot;http://www.foo.com/ns/&quot;, &quot;foo&quot;);
0199:         * w.endDocument();
0200:         * </pre>
0201:         * 
0202:         * <p>
0203:         * The resulting document will look like this:
0204:         * </p>
0205:         * 
0206:         * <pre>
0207:         *           &lt;?xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt;
0208:         *          
0209:         *           &lt;foo:foo xmlns:foo=&quot;http://www.foo.com/ns/&quot;/&gt;
0210:         * </pre>
0211:         * 
0212:         * <p>
0213:         * The default Namespace simply uses an empty string as the prefix:
0214:         * </p>
0215:         * 
0216:         * <pre>
0217:         * w.setPrefix(&quot;http://www.foo.com/ns/&quot;, &quot;&quot;);
0218:         * w.startDocument();
0219:         * w.emptyElement(&quot;http://www.foo.com/ns/&quot;, &quot;foo&quot;);
0220:         * w.endDocument();
0221:         * </pre>
0222:         * 
0223:         * <p>
0224:         * The resulting document will look like this:
0225:         * </p>
0226:         * 
0227:         * <pre>
0228:         *           &lt;?xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt;
0229:         *          
0230:         *           &lt;foo xmlns=&quot;http://www.foo.com/ns/&quot;/&gt;
0231:         * </pre>
0232:         * 
0233:         * <p>
0234:         * By default, the XML writer will not declare a Namespace until it is actually
0235:         * used. Sometimes, this approach will create a large number of Namespace
0236:         * declarations, as in the following example:
0237:         * </p>
0238:         * 
0239:         * <pre>
0240:         *           &lt;xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt;
0241:         *          
0242:         *           &lt;rdf:RDF xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
0243:         *            &lt;rdf:Description about=&quot;http://www.foo.com/ids/books/12345&quot;&gt;
0244:         *             &lt;dc:title xmlns:dc=&quot;http://www.purl.org/dc/&quot;&gt;A Dark Night&lt;/dc:title&gt;
0245:         *             &lt;dc:creator xmlns:dc=&quot;http://www.purl.org/dc/&quot;&gt;Jane Smith&lt;/dc:title&gt;
0246:         *             &lt;dc:date xmlns:dc=&quot;http://www.purl.org/dc/&quot;&gt;2000-09-09&lt;/dc:title&gt;
0247:         *            &lt;/rdf:Description&gt;
0248:         *           &lt;/rdf:RDF&gt;
0249:         * </pre>
0250:         * 
0251:         * <p>
0252:         * The "rdf" prefix is declared only once, because the RDF Namespace is used by
0253:         * the root element and can be inherited by all of its descendants; the "dc"
0254:         * prefix, on the other hand, is declared three times, because no higher element
0255:         * uses the Namespace. To solve this problem, you can instruct the XML writer to
0256:         * predeclare Namespaces on the root element even if they are not used there:
0257:         * </p>
0258:         * 
0259:         * <pre>
0260:         * w.forceNSDecl(&quot;http://www.purl.org/dc/&quot;);
0261:         * </pre>
0262:         * 
0263:         * <p>
0264:         * Now, the "dc" prefix will be declared on the root element even though it's
0265:         * not needed there, and can be inherited by its descendants:
0266:         * </p>
0267:         * 
0268:         * <pre>
0269:         *           &lt;xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt;
0270:         *          
0271:         *           &lt;rdf:RDF xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;
0272:         *                       xmlns:dc=&quot;http://www.purl.org/dc/&quot;&gt;
0273:         *            &lt;rdf:Description about=&quot;http://www.foo.com/ids/books/12345&quot;&gt;
0274:         *             &lt;dc:title&gt;A Dark Night&lt;/dc:title&gt;
0275:         *             &lt;dc:creator&gt;Jane Smith&lt;/dc:title&gt;
0276:         *             &lt;dc:date&gt;2000-09-09&lt;/dc:title&gt;
0277:         *            &lt;/rdf:Description&gt;
0278:         *           &lt;/rdf:RDF&gt;
0279:         * </pre>
0280:         * 
0281:         * <p>
0282:         * This approach is also useful for declaring Namespace prefixes that be used by
0283:         * qualified names appearing in attribute values or character data.
0284:         * </p>
0285:         * 
0286:         * <h2>Data Format</h2>
0287:         * 
0288:         * <p>
0289:         * This mode, enabled by the "dataFormat" property, pretty-prints field-oriented
0290:         * XML without mixed content. All added indentation and newlines will be passed
0291:         * on down the filter chain (if any).
0292:         * </p>
0293:         * 
0294:         * <p>
0295:         * In general, all whitespace in an XML document is potentially significant, so
0296:         * a general-purpose XML writing tool cannot add newlines or indentation.
0297:         * </p>
0298:         * 
0299:         * <p>
0300:         * There is, however, a large class of XML documents where information is
0301:         * strictly fielded: each element contains either character data or other
0302:         * elements, but not both. For this special case, it is possible for a writing
0303:         * tool to provide automatic indentation and newlines without requiring extra
0304:         * work from the user. Note that this class will likely not yield appropriate
0305:         * results for document-oriented XML like XHTML pages, which mix character data
0306:         * and elements together.
0307:         * </p>
0308:         * 
0309:         * <p>
0310:         * This writer mode will automatically place each start tag on a new line,
0311:         * optionally indented if an indent step is provided (by default, there is no
0312:         * indentation). If an element contains other elements, the end tag will also
0313:         * appear on a new line with leading indentation. Consider, for example, the
0314:         * following code:
0315:         * </p>
0316:         * 
0317:         * <pre>
0318:         * XmlWriter w = new XmlWriter();
0319:         * w.setDataFormat(true);
0320:         * w.setIndentStep(2);
0321:         * w.startDocument();
0322:         * w.startElement(&quot;Person&quot;);
0323:         * w.dataElement(&quot;name&quot;, &quot;Jane Smith&quot;);
0324:         * w.dataElement(&quot;date-of-birth&quot;, &quot;1965-05-23&quot;);
0325:         * w.dataElement(&quot;citizenship&quot;, &quot;US&quot;);
0326:         * w.endElement(&quot;Person&quot;);
0327:         * w.endDocument();
0328:         * </pre>
0329:         * 
0330:         * <p>
0331:         * This code will produce the following document:
0332:         * </p>
0333:         * 
0334:         * <pre>
0335:         *           &lt;?xml version=&quot;1.0&quot; standalone=&quot;yes&quot;?&gt;
0336:         *          
0337:         *           &lt;Person&gt;
0338:         *             &lt;name&gt;Jane Smith&lt;/name&gt;
0339:         *             &lt;date-of-birth&gt;1965-05-23&lt;/date-of-birth&gt;
0340:         *             &lt;citizenship&gt;US&lt;/citizenship&gt;
0341:         *           &lt;/Person&gt;
0342:         * </pre>
0343:         * 
0344:         * @see org.xml.sax.XMLFilter
0345:         * @see org.xml.sax.ContentHandler
0346:         * @author David Megginson, Jerome Louvel (contact@noelios.com)
0347:         */
0348:        public final class XmlWriter extends XMLFilterImpl {
0349:            private static final Object SEEN_NOTHING = new Object();
0350:
0351:            private static final Object SEEN_ELEMENT = new Object();
0352:
0353:            private static final Object SEEN_DATA = new Object();
0354:
0355:            /**
0356:             * Constant representing empty attributes.
0357:             */
0358:            private final Attributes EMPTY_ATTS = new AttributesImpl();
0359:
0360:            /**
0361:             * The prefixes table.
0362:             */
0363:            private Map<String, String> prefixTable;
0364:
0365:            /**
0366:             * The forced declarations table.
0367:             */
0368:            private Map<String, Boolean> forcedDeclTable;
0369:
0370:            /**
0371:             * The document declarations table.
0372:             */
0373:            private Map<String, String> doneDeclTable;
0374:
0375:            /**
0376:             * The element level.
0377:             */
0378:            private int elementLevel = 0;
0379:
0380:            /**
0381:             * The namespace support.
0382:             */
0383:            private NamespaceSupport nsSupport;
0384:
0385:            /**
0386:             * The prefix counter.
0387:             */
0388:            private int prefixCounter = 0;
0389:
0390:            /**
0391:             * The underlying writer.
0392:             */
0393:            private Writer output;
0394:
0395:            private Object state = SEEN_NOTHING;
0396:
0397:            private Stack<Object> stateStack = new Stack<Object>();
0398:
0399:            private boolean dataFormat = false;
0400:
0401:            private int indentStep = 0;
0402:
0403:            private int depth = 0;
0404:
0405:            /**
0406:             * Create a new XML writer.
0407:             * <p>
0408:             * Write to standard output.
0409:             * </p>
0410:             */
0411:            public XmlWriter() {
0412:                init(null);
0413:            }
0414:
0415:            /**
0416:             * Constructor.
0417:             * 
0418:             * @param out
0419:             *            The underlying output stream.
0420:             */
0421:            public XmlWriter(OutputStream out) {
0422:                this (new OutputStreamWriter(out));
0423:            }
0424:
0425:            /**
0426:             * Constructor.
0427:             * 
0428:             * @param out
0429:             *            The underlying output stream.
0430:             */
0431:            public XmlWriter(OutputStream out, Charset cs) {
0432:                this (new OutputStreamWriter(out, cs));
0433:            }
0434:
0435:            /**
0436:             * Constructor.
0437:             * 
0438:             * @param out
0439:             *            The underlying output stream.
0440:             */
0441:            public XmlWriter(OutputStream out, CharsetEncoder enc) {
0442:                this (new OutputStreamWriter(out, enc));
0443:            }
0444:
0445:            /**
0446:             * Constructor.
0447:             * 
0448:             * @param out
0449:             *            The underlying output stream.
0450:             */
0451:            public XmlWriter(OutputStream out, String charsetName)
0452:                    throws UnsupportedEncodingException {
0453:                this (new OutputStreamWriter(out, charsetName));
0454:            }
0455:
0456:            /**
0457:             * Create a new XML writer.
0458:             * <p>
0459:             * Write to the writer provided.
0460:             * </p>
0461:             * 
0462:             * @param writer
0463:             *            The output destination, or null to use standard output.
0464:             */
0465:            public XmlWriter(Writer writer) {
0466:                init(writer);
0467:            }
0468:
0469:            /**
0470:             * Create a new XML writer.
0471:             * <p>
0472:             * Use the specified XML reader as the parent.
0473:             * </p>
0474:             * 
0475:             * @param xmlreader
0476:             *            The parent in the filter chain, or null for no parent.
0477:             */
0478:            public XmlWriter(XMLReader xmlreader) {
0479:                super (xmlreader);
0480:                init(null);
0481:            }
0482:
0483:            /**
0484:             * Create a new XML writer.
0485:             * <p>
0486:             * Use the specified XML reader as the parent, and write to the specified
0487:             * writer.
0488:             * </p>
0489:             * 
0490:             * @param xmlreader
0491:             *            The parent in the filter chain, or null for no parent.
0492:             * @param writer
0493:             *            The output destination, or null to use standard output.
0494:             */
0495:            public XmlWriter(XMLReader xmlreader, Writer writer) {
0496:                super (xmlreader);
0497:                init(writer);
0498:            }
0499:
0500:            /**
0501:             * Write character data. Pass the event on down the filter chain for further
0502:             * processing.
0503:             * 
0504:             * @param ch
0505:             *            The array of characters to write.
0506:             * @param start
0507:             *            The starting position in the array.
0508:             * @param len
0509:             *            The number of characters to write.
0510:             * @exception org.xml.sax.SAXException
0511:             *                If there is an error writing the characters, or if a
0512:             *                restlet further down the filter chain raises an exception.
0513:             * @see org.xml.sax.ContentHandler#characters
0514:             */
0515:            private void characters(boolean dataFormat, char ch[], int start,
0516:                    int len) throws SAXException {
0517:                if (dataFormat) {
0518:                    state = SEEN_DATA;
0519:                }
0520:
0521:                writeEsc(ch, start, len, false);
0522:                super .characters(ch, start, len);
0523:            }
0524:
0525:            // //////////////////////////////////////////////////////////////////
0526:            // Public methods.
0527:            // //////////////////////////////////////////////////////////////////
0528:
0529:            /**
0530:             * Write a string of character data, with XML escaping.
0531:             * <p>
0532:             * This is a convenience method that takes an XML String, converts it to a
0533:             * character array, then invokes {@link #characters(char[], int, int)}.
0534:             * </p>
0535:             * 
0536:             * @param data
0537:             *            The character data.
0538:             * @exception org.xml.sax.SAXException
0539:             *                If there is an error writing the string, or if a restlet
0540:             *                further down the filter chain raises an exception.
0541:             * @see #characters(char[], int, int)
0542:             */
0543:            private void characters(boolean dataFormat, String data)
0544:                    throws SAXException {
0545:                char ch[] = data.toCharArray();
0546:                characters(dataFormat, ch, 0, ch.length);
0547:            }
0548:
0549:            /**
0550:             * Write character data. Pass the event on down the filter chain for further
0551:             * processing.
0552:             * 
0553:             * @param ch
0554:             *            The array of characters to write.
0555:             * @param start
0556:             *            The starting position in the array.
0557:             * @param len
0558:             *            The number of characters to write.
0559:             * @exception org.xml.sax.SAXException
0560:             *                If there is an error writing the characters, or if a
0561:             *                restlet further down the filter chain raises an exception.
0562:             * @see org.xml.sax.ContentHandler#characters
0563:             */
0564:            public void characters(char ch[], int start, int len)
0565:                    throws SAXException {
0566:                characters(isDataFormat(), ch, start, len);
0567:            }
0568:
0569:            /**
0570:             * Write a string of character data, with XML escaping.
0571:             * <p>
0572:             * This is a convenience method that takes an XML String, converts it to a
0573:             * character array, then invokes {@link #characters(char[], int, int)}.
0574:             * </p>
0575:             * 
0576:             * @param data
0577:             *            The character data.
0578:             * @exception org.xml.sax.SAXException
0579:             *                If there is an error writing the string, or if a restlet
0580:             *                further down the filter chain raises an exception.
0581:             * @see #characters(char[], int, int)
0582:             */
0583:            public void characters(String data) throws SAXException {
0584:                characters(false, data);
0585:            }
0586:
0587:            /**
0588:             * Write an element with character data content but no attributes or
0589:             * Namespace URI.
0590:             * 
0591:             * <p>
0592:             * This is a convenience method to write a complete element with character
0593:             * data content, including the start tag and end tag. The method provides an
0594:             * empty string for the Namespace URI, and empty string for the qualified
0595:             * name, and an empty attribute list.
0596:             * </p>
0597:             * 
0598:             * <p>
0599:             * This method invokes
0600:             * {@link #startElement(String, String, String, Attributes)}, followed by
0601:             * {@link #characters(String)}, followed by
0602:             * {@link #endElement(String, String, String)}.
0603:             * </p>
0604:             * 
0605:             * @param localName
0606:             *            The element's local name.
0607:             * @param content
0608:             *            The character data content.
0609:             * @exception org.xml.sax.SAXException
0610:             *                If there is an error writing the empty tag, or if a
0611:             *                restlet further down the filter chain raises an exception.
0612:             * @see #startElement(String, String, String, Attributes)
0613:             * @see #characters(String)
0614:             * @see #endElement(String, String, String)
0615:             */
0616:            public void dataElement(String localName, String content)
0617:                    throws SAXException {
0618:                dataElement("", localName, "", EMPTY_ATTS, content);
0619:            }
0620:
0621:            /**
0622:             * Write an element with character data content but no attributes.
0623:             * 
0624:             * <p>
0625:             * This is a convenience method to write a complete element with character
0626:             * data content, including the start tag and end tag. This method provides
0627:             * an empty string for the qname and an empty attribute list.
0628:             * </p>
0629:             * 
0630:             * <p>
0631:             * This method invokes
0632:             * {@link #startElement(String, String, String, Attributes)}, followed by
0633:             * {@link #characters(String)}, followed by
0634:             * {@link #endElement(String, String, String)}.
0635:             * </p>
0636:             * 
0637:             * @param uri
0638:             *            The element's Namespace URI.
0639:             * @param localName
0640:             *            The element's local name.
0641:             * @param content
0642:             *            The character data content.
0643:             * @exception org.xml.sax.SAXException
0644:             *                If there is an error writing the empty tag, or if a
0645:             *                restlet further down the filter chain raises an exception.
0646:             * @see #startElement(String, String, String, Attributes)
0647:             * @see #characters(String)
0648:             * @see #endElement(String, String, String)
0649:             */
0650:            public void dataElement(String uri, String localName, String content)
0651:                    throws SAXException {
0652:                dataElement(uri, localName, "", EMPTY_ATTS, content);
0653:            }
0654:
0655:            /**
0656:             * Write an element with character data content.
0657:             * 
0658:             * <p>
0659:             * This is a convenience method to write a complete element with character
0660:             * data content, including the start tag and end tag.
0661:             * </p>
0662:             * 
0663:             * <p>
0664:             * This method invokes
0665:             * {@link #startElement(String, String, String, Attributes)}, followed by
0666:             * {@link #characters(String)}, followed by
0667:             * {@link #endElement(String, String, String)}.
0668:             * </p>
0669:             * 
0670:             * @param uri
0671:             *            The element's Namespace URI.
0672:             * @param localName
0673:             *            The element's local name.
0674:             * @param qName
0675:             *            The element's default qualified name.
0676:             * @param atts
0677:             *            The element's attributes.
0678:             * @param content
0679:             *            The character data content.
0680:             * @exception org.xml.sax.SAXException
0681:             *                If there is an error writing the empty tag, or if a
0682:             *                restlet further down the filter chain raises an exception.
0683:             * @see #startElement(String, String, String, Attributes)
0684:             * @see #characters(String)
0685:             * @see #endElement(String, String, String)
0686:             */
0687:            public void dataElement(String uri, String localName, String qName,
0688:                    Attributes atts, String content) throws SAXException {
0689:                startElement(uri, localName, qName, atts);
0690:                characters(content);
0691:                endElement(uri, localName, qName);
0692:            }
0693:
0694:            /**
0695:             * Print indentation for the current level.
0696:             * 
0697:             * @exception org.xml.sax.SAXException
0698:             *                If there is an error writing the indentation characters,
0699:             *                or if a filter further down the chain raises an exception.
0700:             */
0701:            private void doIndent() throws SAXException {
0702:                if ((indentStep > 0) && (depth > 0)) {
0703:                    int n = indentStep * depth;
0704:                    char ch[] = new char[n];
0705:                    for (int i = 0; i < n; i++) {
0706:                        ch[i] = ' ';
0707:                    }
0708:                    characters(ch, 0, n);
0709:                }
0710:            }
0711:
0712:            /**
0713:             * Determine the prefix for an element or attribute name. TODO: this method
0714:             * probably needs some cleanup.
0715:             * 
0716:             * @param uri
0717:             *            The Namespace URI.
0718:             * @param qName
0719:             *            The qualified name (optional); this will be used to indicate
0720:             *            the preferred prefix if none is currently bound.
0721:             * @param isElement
0722:             *            true if this is an element name, false if it is an attribute
0723:             *            name (which cannot use the default Namespace).
0724:             */
0725:            private String doPrefix(String uri, String qName, boolean isElement) {
0726:                String defaultNS = nsSupport.getURI("");
0727:                if ("".equals(uri)) {
0728:                    if (isElement && (defaultNS != null))
0729:                        nsSupport.declarePrefix("", "");
0730:                    return null;
0731:                }
0732:                String prefix;
0733:                if (isElement && (defaultNS != null) && uri.equals(defaultNS)) {
0734:                    prefix = "";
0735:                } else {
0736:                    prefix = nsSupport.getPrefix(uri);
0737:                }
0738:                if (prefix != null) {
0739:                    return prefix;
0740:                }
0741:                prefix = doneDeclTable.get(uri);
0742:                if ((prefix != null)
0743:                        && (((!isElement || (defaultNS != null)) && ""
0744:                                .equals(prefix)) || (nsSupport.getURI(prefix) != null))) {
0745:                    prefix = null;
0746:                }
0747:                if (prefix == null) {
0748:                    prefix = prefixTable.get(uri);
0749:                    if ((prefix != null)
0750:                            && (((!isElement || (defaultNS != null)) && ""
0751:                                    .equals(prefix)) || (nsSupport
0752:                                    .getURI(prefix) != null))) {
0753:                        prefix = null;
0754:                    }
0755:                }
0756:                if ((prefix == null) && (qName != null) && !"".equals(qName)) {
0757:                    int i = qName.indexOf(':');
0758:                    if (i == -1) {
0759:                        if (isElement && (defaultNS == null)) {
0760:                            prefix = "";
0761:                        }
0762:                    } else {
0763:                        prefix = qName.substring(0, i);
0764:                    }
0765:                }
0766:                for (; (prefix == null) || (nsSupport.getURI(prefix) != null); prefix = "__NS"
0767:                        + ++prefixCounter)
0768:                    ;
0769:                nsSupport.declarePrefix(prefix, uri);
0770:                doneDeclTable.put(uri, prefix);
0771:                return prefix;
0772:            }
0773:
0774:            // //////////////////////////////////////////////////////////////////
0775:            // Methods from org.xml.sax.ContentHandler.
0776:            // //////////////////////////////////////////////////////////////////
0777:
0778:            /**
0779:             * Add an empty element without a Namespace URI, qname or attributes.
0780:             * 
0781:             * <p>
0782:             * This method will supply an empty string for the qname, and empty string
0783:             * for the Namespace URI, and an empty attribute list. It invokes
0784:             * {@link #emptyElement(String, String, String, Attributes)} directly.
0785:             * </p>
0786:             * 
0787:             * @param localName
0788:             *            The element's local name.
0789:             * @exception org.xml.sax.SAXException
0790:             *                If there is an error writing the empty tag, or if a
0791:             *                restlet further down the filter chain raises an exception.
0792:             * @see #emptyElement(String, String, String, Attributes)
0793:             */
0794:            public void emptyElement(String localName) throws SAXException {
0795:                emptyElement("", localName, "", EMPTY_ATTS);
0796:            }
0797:
0798:            /**
0799:             * Add an empty element without a qname or attributes.
0800:             * 
0801:             * <p>
0802:             * This method will supply an empty string for the qname and an empty
0803:             * attribute list. It invokes
0804:             * {@link #emptyElement(String, String, String, Attributes)} directly.
0805:             * </p>
0806:             * 
0807:             * @param uri
0808:             *            The element's Namespace URI.
0809:             * @param localName
0810:             *            The element's local name.
0811:             * @exception org.xml.sax.SAXException
0812:             *                If there is an error writing the empty tag, or if a
0813:             *                restlet further down the filter chain raises an exception.
0814:             * @see #emptyElement(String, String, String, Attributes)
0815:             */
0816:            public void emptyElement(String uri, String localName)
0817:                    throws SAXException {
0818:                emptyElement(uri, localName, "", EMPTY_ATTS);
0819:            }
0820:
0821:            /**
0822:             * Write an empty element. This method writes an empty element tag rather
0823:             * than a start tag followed by an end tag. Both a
0824:             * {@link #startElement startElement} and an {@link #endElement endElement}
0825:             * event will be passed on down the filter chain.
0826:             * 
0827:             * @param uri
0828:             *            The element's Namespace URI, or the empty string if the
0829:             *            element has no Namespace or if Namespace processing is not
0830:             *            being performed.
0831:             * @param localName
0832:             *            The element's local name (without prefix). This parameter must
0833:             *            be provided.
0834:             * @param qName
0835:             *            The element's qualified name (with prefix), or the empty
0836:             *            string if none is available. This parameter is strictly
0837:             *            advisory: the writer may or may not use the prefix attached.
0838:             * @param atts
0839:             *            The element's attribute list.
0840:             * @exception org.xml.sax.SAXException
0841:             *                If there is an error writing the empty tag, or if a
0842:             *                restlet further down the filter chain raises an exception.
0843:             * @see #startElement
0844:             * @see #endElement
0845:             */
0846:            public void emptyElement(String uri, String localName,
0847:                    String qName, Attributes atts) throws SAXException {
0848:                if (isDataFormat()) {
0849:                    state = SEEN_ELEMENT;
0850:                    if (depth > 0) {
0851:                        characters(false, "\n");
0852:                    }
0853:                    doIndent();
0854:                }
0855:
0856:                nsSupport.pushContext();
0857:                write('<');
0858:                writeName(uri, localName, qName, true);
0859:                writeAttributes(atts);
0860:                if (elementLevel == 1) {
0861:                    forceNSDecls();
0862:                }
0863:                writeNSDecls();
0864:                write("/>");
0865:                super .startElement(uri, localName, qName, atts);
0866:                super .endElement(uri, localName, qName);
0867:            }
0868:
0869:            /**
0870:             * Write a newline at the end of the document. Pass the event on down the
0871:             * filter chain for further processing.
0872:             * 
0873:             * @exception org.xml.sax.SAXException
0874:             *                If there is an error writing the newline, or if a restlet
0875:             *                further down the filter chain raises an exception.
0876:             * @see org.xml.sax.ContentHandler#endDocument
0877:             */
0878:            public void endDocument() throws SAXException {
0879:                write('\n');
0880:                super .endDocument();
0881:                try {
0882:                    flush();
0883:                } catch (IOException e) {
0884:                    throw new SAXException(e);
0885:                }
0886:            }
0887:
0888:            /**
0889:             * End an element without a Namespace URI or qname.
0890:             * 
0891:             * <p>
0892:             * This method will supply an empty string for the qName and an empty string
0893:             * for the Namespace URI. It invokes
0894:             * {@link #endElement(String, String, String)} directly.
0895:             * </p>
0896:             * 
0897:             * @param localName
0898:             *            The element's local name.
0899:             * @exception org.xml.sax.SAXException
0900:             *                If there is an error writing the end tag, or if a restlet
0901:             *                further down the filter chain raises an exception.
0902:             * @see #endElement(String, String, String)
0903:             */
0904:            public void endElement(String localName) throws SAXException {
0905:                endElement("", localName, "");
0906:            }
0907:
0908:            /**
0909:             * End an element without a qname.
0910:             * 
0911:             * <p>
0912:             * This method will supply an empty string for the qName. It invokes
0913:             * {@link #endElement(String, String, String)} directly.
0914:             * </p>
0915:             * 
0916:             * @param uri
0917:             *            The element's Namespace URI.
0918:             * @param localName
0919:             *            The element's local name.
0920:             * @exception org.xml.sax.SAXException
0921:             *                If there is an error writing the end tag, or if a restlet
0922:             *                further down the filter chain raises an exception.
0923:             * @see #endElement(String, String, String)
0924:             */
0925:            public void endElement(String uri, String localName)
0926:                    throws SAXException {
0927:                endElement(uri, localName, "");
0928:            }
0929:
0930:            /**
0931:             * Write an end tag. Pass the event on down the filter chain for further
0932:             * processing.
0933:             * 
0934:             * @param uri
0935:             *            The Namespace URI, or the empty string if none is available.
0936:             * @param localName
0937:             *            The element's local (unprefixed) name (required).
0938:             * @param qName
0939:             *            The element's qualified (prefixed) name, or the empty string
0940:             *            is none is available. This method will use the qName as a
0941:             *            template for generating a prefix if necessary, but it is not
0942:             *            guaranteed to use the same qName.
0943:             * @exception org.xml.sax.SAXException
0944:             *                If there is an error writing the end tag, or if a restlet
0945:             *                further down the filter chain raises an exception.
0946:             * @see org.xml.sax.ContentHandler#endElement
0947:             */
0948:            public void endElement(String uri, String localName, String qName)
0949:                    throws SAXException {
0950:                if (isDataFormat()) {
0951:                    depth--;
0952:                    if (state == SEEN_ELEMENT) {
0953:                        characters(false, "\n");
0954:                        doIndent();
0955:                    }
0956:                }
0957:
0958:                write("</");
0959:                writeName(uri, localName, qName, true);
0960:                write('>');
0961:                if (elementLevel == 1) {
0962:                    write('\n');
0963:                }
0964:                super .endElement(uri, localName, qName);
0965:                nsSupport.popContext();
0966:                elementLevel--;
0967:
0968:                if (isDataFormat()) {
0969:                    state = stateStack.pop();
0970:                }
0971:            }
0972:
0973:            /**
0974:             * Flush the output.
0975:             * <p>
0976:             * This method flushes the output stream. It is especially useful when you
0977:             * need to make certain that the entire document has been written to output
0978:             * but do not want to close the output stream.
0979:             * </p>
0980:             * <p>
0981:             * This method is invoked automatically by the
0982:             * {@link #endDocument endDocument} method after writing a document.
0983:             * </p>
0984:             * 
0985:             * @see #reset
0986:             */
0987:            public void flush() throws IOException {
0988:                output.flush();
0989:            }
0990:
0991:            // //////////////////////////////////////////////////////////////////
0992:            // Additional markup.
0993:            // //////////////////////////////////////////////////////////////////
0994:
0995:            /**
0996:             * Force a Namespace to be declared on the root element.
0997:             * <p>
0998:             * By default, the XMLWriter will declare only the Namespaces needed for an
0999:             * element; as a result, a Namespace may be declared many places in a
1000:             * document if it is not used on the root element.
1001:             * </p>
1002:             * <p>
1003:             * This method forces a Namespace to be declared on the root element even if
1004:             * it is not used there, and reduces the number of xmlns attributes in the
1005:             * document.
1006:             * </p>
1007:             * 
1008:             * @param uri
1009:             *            The Namespace URI to declare.
1010:             * @see #forceNSDecl(java.lang.String,java.lang.String)
1011:             * @see #setPrefix
1012:             */
1013:            public void forceNSDecl(String uri) {
1014:                forcedDeclTable.put(uri, Boolean.TRUE);
1015:            }
1016:
1017:            // //////////////////////////////////////////////////////////////////
1018:            // Convenience methods.
1019:            // //////////////////////////////////////////////////////////////////
1020:
1021:            /**
1022:             * Force a Namespace declaration with a preferred prefix.
1023:             * <p>
1024:             * This is a convenience method that invokes {@link #setPrefix setPrefix}
1025:             * then {@link #forceNSDecl(java.lang.String) forceNSDecl}.
1026:             * </p>
1027:             * 
1028:             * @param uri
1029:             *            The Namespace URI to declare on the root element.
1030:             * @param prefix
1031:             *            The preferred prefix for the Namespace, or "" for the default
1032:             *            Namespace.
1033:             * @see #setPrefix
1034:             * @see #forceNSDecl(java.lang.String)
1035:             */
1036:            public void forceNSDecl(String uri, String prefix) {
1037:                setPrefix(uri, prefix);
1038:                forceNSDecl(uri);
1039:            }
1040:
1041:            /**
1042:             * Force all Namespaces to be declared. This method is used on the root
1043:             * element to ensure that the predeclared Namespaces all appear.
1044:             */
1045:            private void forceNSDecls() {
1046:                for (String prefix : forcedDeclTable.keySet()) {
1047:                    doPrefix(prefix, null, true);
1048:                }
1049:            }
1050:
1051:            /**
1052:             * Return the current indent step.
1053:             * <p>
1054:             * Return the current indent step: each start tag will be indented by this
1055:             * number of spaces times the number of ancestors that the element has.
1056:             * </p>
1057:             * 
1058:             * @return The number of spaces in each indentation step, or 0 or less for
1059:             *         no indentation.
1060:             */
1061:            public int getIndentStep() {
1062:                return indentStep;
1063:            }
1064:
1065:            /**
1066:             * Get the current or preferred prefix for a Namespace URI.
1067:             * 
1068:             * @param uri
1069:             *            The Namespace URI.
1070:             * @return The preferred prefix, or "" for the default Namespace.
1071:             * @see #setPrefix
1072:             */
1073:            public String getPrefix(String uri) {
1074:                return prefixTable.get(uri);
1075:            }
1076:
1077:            /**
1078:             * Returns the underlying writer.
1079:             * 
1080:             * @return The underlying writer.
1081:             */
1082:            public Writer getWriter() {
1083:                return this .output;
1084:            }
1085:
1086:            /**
1087:             * Write ignorable whitespace. Pass the event on down the filter chain for
1088:             * further processing.
1089:             * 
1090:             * @param ch
1091:             *            The array of characters to write.
1092:             * @param start
1093:             *            The starting position in the array.
1094:             * @param length
1095:             *            The number of characters to write.
1096:             * @exception org.xml.sax.SAXException
1097:             *                If there is an error writing the whitespace, or if a
1098:             *                restlet further down the filter chain raises an exception.
1099:             * @see org.xml.sax.ContentHandler#ignorableWhitespace
1100:             */
1101:            public void ignorableWhitespace(char ch[], int start, int length)
1102:                    throws SAXException {
1103:                writeEsc(ch, start, length, false);
1104:                super .ignorableWhitespace(ch, start, length);
1105:            }
1106:
1107:            /**
1108:             * Internal initialization method.
1109:             * 
1110:             * <p>
1111:             * All of the public constructors invoke this method.
1112:             * 
1113:             * @param writer
1114:             *            The output destination, or null to use standard output.
1115:             */
1116:            private void init(Writer writer) {
1117:                setOutput(writer);
1118:                nsSupport = new NamespaceSupport();
1119:                prefixTable = new TreeMap<String, String>();
1120:                forcedDeclTable = new TreeMap<String, Boolean>();
1121:                doneDeclTable = new TreeMap<String, String>();
1122:            }
1123:
1124:            public boolean isDataFormat() {
1125:                return this .dataFormat;
1126:            }
1127:
1128:            /**
1129:             * Write a processing instruction. Pass the event on down the filter chain
1130:             * for further processing.
1131:             * 
1132:             * @param target
1133:             *            The PI target.
1134:             * @param data
1135:             *            The PI data.
1136:             * @exception org.xml.sax.SAXException
1137:             *                If there is an error writing the PI, or if a restlet
1138:             *                further down the filter chain raises an exception.
1139:             * @see org.xml.sax.ContentHandler#processingInstruction
1140:             */
1141:            public void processingInstruction(String target, String data)
1142:                    throws SAXException {
1143:                write("<?");
1144:                write(target);
1145:                write(' ');
1146:                write(data);
1147:                write("?>");
1148:                if (elementLevel < 1) {
1149:                    write('\n');
1150:                }
1151:                super .processingInstruction(target, data);
1152:            }
1153:
1154:            /**
1155:             * Reset the writer.
1156:             * 
1157:             * <p>
1158:             * This method is especially useful if the writer throws an exception before
1159:             * it is finished, and you want to reuse the writer for a new document. It
1160:             * is usually a good idea to invoke {@link #flush flush} before resetting
1161:             * the writer, to make sure that no output is lost.
1162:             * </p>
1163:             * 
1164:             * <p>
1165:             * This method is invoked automatically by the
1166:             * {@link #startDocument startDocument} method before writing a new
1167:             * document.
1168:             * </p>
1169:             * 
1170:             * <p>
1171:             * <strong>Note:</strong> this method will <em>not</em> clear the prefix
1172:             * or URI information in the writer or the selected output writer.
1173:             * </p>
1174:             * 
1175:             * @see #flush
1176:             */
1177:            public void reset() {
1178:                if (isDataFormat()) {
1179:                    depth = 0;
1180:                    state = SEEN_NOTHING;
1181:                    stateStack = new Stack<Object>();
1182:                }
1183:
1184:                elementLevel = 0;
1185:                prefixCounter = 0;
1186:                nsSupport.reset();
1187:            }
1188:
1189:            public void setDataFormat(boolean dataFormat) {
1190:                this .dataFormat = dataFormat;
1191:            }
1192:
1193:            // //////////////////////////////////////////////////////////////////
1194:            // Internal methods.
1195:            // //////////////////////////////////////////////////////////////////
1196:
1197:            /**
1198:             * Set the current indent step.
1199:             * 
1200:             * @param indentStep
1201:             *            The new indent step (0 or less for no indentation).
1202:             */
1203:            public void setIndentStep(int indentStep) {
1204:                this .indentStep = indentStep;
1205:            }
1206:
1207:            /**
1208:             * Set a new output destination for the document.
1209:             * 
1210:             * @param writer
1211:             *            The output destination, or null to use standard output.
1212:             * @see #flush
1213:             */
1214:            public void setOutput(Writer writer) {
1215:                if (writer == null) {
1216:                    output = new OutputStreamWriter(System.out);
1217:                } else {
1218:                    output = writer;
1219:                }
1220:            }
1221:
1222:            /**
1223:             * Specify a preferred prefix for a Namespace URI.
1224:             * <p>
1225:             * Note that this method does not actually force the Namespace to be
1226:             * declared; to do that, use the
1227:             * {@link  #forceNSDecl(java.lang.String) forceNSDecl} method as well.
1228:             * </p>
1229:             * 
1230:             * @param uri
1231:             *            The Namespace URI.
1232:             * @param prefix
1233:             *            The preferred prefix, or "" to select the default Namespace.
1234:             * @see #getPrefix
1235:             * @see #forceNSDecl(java.lang.String)
1236:             * @see #forceNSDecl(java.lang.String,java.lang.String)
1237:             */
1238:            public void setPrefix(String uri, String prefix) {
1239:                prefixTable.put(uri, prefix);
1240:            }
1241:
1242:            /**
1243:             * Write the XML declaration at the beginning of the document. Pass the
1244:             * event on down the filter chain for further processing.
1245:             * 
1246:             * @exception org.xml.sax.SAXException
1247:             *                If there is an error writing the XML declaration, or if a
1248:             *                restlet further down the filter chain raises an exception.
1249:             * @see org.xml.sax.ContentHandler#startDocument
1250:             */
1251:            public void startDocument() throws SAXException {
1252:                reset();
1253:                write("<?xml version=\"1.0\" standalone=\"yes\"?>\n\n");
1254:                super .startDocument();
1255:            }
1256:
1257:            /**
1258:             * Start a new element without a qname, attributes or a Namespace URI.
1259:             * 
1260:             * <p>
1261:             * This method will provide an empty string for the Namespace URI, and empty
1262:             * string for the qualified name, and a default empty attribute list. It
1263:             * invokes #startElement(String, String, String, Attributes)} directly.
1264:             * </p>
1265:             * 
1266:             * @param localName
1267:             *            The element's local name.
1268:             * @exception org.xml.sax.SAXException
1269:             *                If there is an error writing the start tag, or if a
1270:             *                restlet further down the filter chain raises an exception.
1271:             * @see #startElement(String, String, String, Attributes)
1272:             */
1273:            public void startElement(String localName) throws SAXException {
1274:                startElement("", localName, "", EMPTY_ATTS);
1275:            }
1276:
1277:            /**
1278:             * Start a new element without a qname or attributes.
1279:             * 
1280:             * <p>
1281:             * This method will provide a default empty attribute list and an empty
1282:             * string for the qualified name. It invokes
1283:             * {@link  #startElement(String, String, String, Attributes)} directly.
1284:             * </p>
1285:             * 
1286:             * @param uri
1287:             *            The element's Namespace URI.
1288:             * @param localName
1289:             *            The element's local name.
1290:             * @exception org.xml.sax.SAXException
1291:             *                If there is an error writing the start tag, or if a
1292:             *                restlet further down the filter chain raises an exception.
1293:             * @see #startElement(String, String, String, Attributes)
1294:             */
1295:            public void startElement(String uri, String localName)
1296:                    throws SAXException {
1297:                startElement(uri, localName, "", EMPTY_ATTS);
1298:            }
1299:
1300:            /**
1301:             * Write a start tag. Pass the event on down the filter chain for further
1302:             * processing.
1303:             * 
1304:             * @param uri
1305:             *            The Namespace URI, or the empty string if none is available.
1306:             * @param localName
1307:             *            The element's local (unprefixed) name (required).
1308:             * @param qName
1309:             *            The element's qualified (prefixed) name, or the empty string
1310:             *            is none is available. This method will use the qName as a
1311:             *            template for generating a prefix if necessary, but it is not
1312:             *            guaranteed to use the same qName.
1313:             * @param atts
1314:             *            The element's attribute list (must not be null).
1315:             * @exception org.xml.sax.SAXException
1316:             *                If there is an error writing the start tag, or if a
1317:             *                restlet further down the filter chain raises an exception.
1318:             * @see org.xml.sax.ContentHandler#startElement
1319:             */
1320:            public void startElement(String uri, String localName,
1321:                    String qName, Attributes atts) throws SAXException {
1322:                if (isDataFormat()) {
1323:                    stateStack.push(SEEN_ELEMENT);
1324:                    state = SEEN_NOTHING;
1325:                    if (depth > 0) {
1326:                        characters("\n");
1327:                    }
1328:                    doIndent();
1329:                }
1330:
1331:                elementLevel++;
1332:                nsSupport.pushContext();
1333:                write('<');
1334:                writeName(uri, localName, qName, true);
1335:                writeAttributes(atts);
1336:                if (elementLevel == 1) {
1337:                    forceNSDecls();
1338:                }
1339:                writeNSDecls();
1340:                write('>');
1341:                super .startElement(uri, localName, qName, atts);
1342:
1343:                if (isDataFormat()) {
1344:                    depth++;
1345:                }
1346:            }
1347:
1348:            /**
1349:             * Write a raw character.
1350:             * 
1351:             * @param c
1352:             *            The character to write.
1353:             * @exception org.xml.sax.SAXException
1354:             *                If there is an error writing the character, this method
1355:             *                will throw an IOException wrapped in a SAXException.
1356:             */
1357:            private void write(char c) throws SAXException {
1358:                try {
1359:                    output.write(c);
1360:                } catch (IOException e) {
1361:                    throw new SAXException(e);
1362:                }
1363:            }
1364:
1365:            /**
1366:             * Write a raw string.
1367:             * 
1368:             * @param s
1369:             * @exception org.xml.sax.SAXException
1370:             *                If there is an error writing the string, this method will
1371:             *                throw an IOException wrapped in a SAXException
1372:             */
1373:            private void write(String s) throws SAXException {
1374:                try {
1375:                    output.write(s);
1376:                } catch (IOException e) {
1377:                    throw new SAXException(e);
1378:                }
1379:            }
1380:
1381:            /**
1382:             * Write out an attribute list, escaping values. The names will have
1383:             * prefixes added to them.
1384:             * 
1385:             * @param atts
1386:             *            The attribute list to write.
1387:             * @exception org.xml.SAXException
1388:             *                If there is an error writing the attribute list, this
1389:             *                method will throw an IOException wrapped in a
1390:             *                SAXException.
1391:             */
1392:            private void writeAttributes(Attributes atts) throws SAXException {
1393:                int len = atts.getLength();
1394:                for (int i = 0; i < len; i++) {
1395:                    char ch[] = atts.getValue(i).toCharArray();
1396:                    write(' ');
1397:                    writeName(atts.getURI(i), atts.getLocalName(i), atts
1398:                            .getQName(i), false);
1399:                    write("=\"");
1400:                    writeEsc(ch, 0, ch.length, true);
1401:                    write('"');
1402:                }
1403:            }
1404:
1405:            /**
1406:             * Write an array of data characters with escaping.
1407:             * 
1408:             * @param ch
1409:             *            The array of characters.
1410:             * @param start
1411:             *            The starting position.
1412:             * @param length
1413:             *            The number of characters to use.
1414:             * @param isAttVal
1415:             *            true if this is an attribute value literal.
1416:             * @exception org.xml.SAXException
1417:             *                If there is an error writing the characters, this method
1418:             *                will throw an IOException wrapped in a SAXException.
1419:             */
1420:            private void writeEsc(char ch[], int start, int length,
1421:                    boolean isAttVal) throws SAXException {
1422:                for (int i = start; i < start + length; i++) {
1423:                    switch (ch[i]) {
1424:                    case '&':
1425:                        write("&amp;");
1426:                        break;
1427:                    case '<':
1428:                        write("&lt;");
1429:                        break;
1430:                    case '>':
1431:                        write("&gt;");
1432:                        break;
1433:                    case '\"':
1434:                        if (isAttVal) {
1435:                            write("&quot;");
1436:                        } else {
1437:                            write('\"');
1438:                        }
1439:                        break;
1440:                    default:
1441:                        if (ch[i] > '\u007f') {
1442:                            write("&#");
1443:                            write(Integer.toString(ch[i]));
1444:                            write(';');
1445:                        } else {
1446:                            write(ch[i]);
1447:                        }
1448:                    }
1449:                }
1450:            }
1451:
1452:            /**
1453:             * Write an element or attribute name.
1454:             * 
1455:             * @param uri
1456:             *            The Namespace URI.
1457:             * @param localName
1458:             *            The local name.
1459:             * @param qName
1460:             *            The prefixed name, if available, or the empty string.
1461:             * @param isElement
1462:             *            true if this is an element name, false if it is an attribute
1463:             *            name.
1464:             * @exception org.xml.sax.SAXException
1465:             *                This method will throw an IOException wrapped in a
1466:             *                SAXException if there is an error writing the name.
1467:             */
1468:            private void writeName(String uri, String localName, String qName,
1469:                    boolean isElement) throws SAXException {
1470:                String prefix = doPrefix(uri, qName, isElement);
1471:                if ((prefix != null) && !"".equals(prefix)) {
1472:                    write(prefix);
1473:                    write(':');
1474:                }
1475:                write(localName);
1476:            }
1477:
1478:            /**
1479:             * Write out the list of Namespace declarations.
1480:             * 
1481:             * @exception org.xml.sax.SAXException
1482:             *                This method will throw an IOException wrapped in a
1483:             *                SAXException if there is an error writing the Namespace
1484:             *                declarations.
1485:             */
1486:            @SuppressWarnings("unchecked")
1487:            private void writeNSDecls() throws SAXException {
1488:                Enumeration<String> prefixes = nsSupport.getDeclaredPrefixes();
1489:                while (prefixes.hasMoreElements()) {
1490:                    String prefix = prefixes.nextElement();
1491:                    String uri = nsSupport.getURI(prefix);
1492:                    if (uri == null) {
1493:                        uri = "";
1494:                    }
1495:                    char ch[] = uri.toCharArray();
1496:                    write(' ');
1497:                    if ("".equals(prefix)) {
1498:                        write("xmlns=\"");
1499:                    } else {
1500:                        write("xmlns:");
1501:                        write(prefix);
1502:                        write("=\"");
1503:                    }
1504:                    writeEsc(ch, 0, ch.length, true);
1505:                    write('\"');
1506:                }
1507:            }
1508:
1509:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.