Source Code Cross Referenced for XMLOutputter.java in  » Workflow-Engines » OpenWFE » org » jdom » output » 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 » Workflow Engines » OpenWFE » org.jdom.output 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*--
0002:
0003:         $Id: XMLOutputter.java,v 1.2 2005/05/03 07:02:04 wittek Exp $
0004:
0005:         Copyright (C) 2000-2004 Jason Hunter & Brett McLaughlin.
0006:         All rights reserved.
0007:
0008:         Redistribution and use in source and binary forms, with or without
0009:         modification, are permitted provided that the following conditions
0010:         are met:
0011:
0012:         1. Redistributions of source code must retain the above copyright
0013:            notice, this list of conditions, and the following disclaimer.
0014:
0015:         2. Redistributions in binary form must reproduce the above copyright
0016:            notice, this list of conditions, and the disclaimer that follows
0017:            these conditions in the documentation and/or other materials
0018:            provided with the distribution.
0019:
0020:         3. The name "JDOM" must not be used to endorse or promote products
0021:            derived from this software without prior written permission.  For
0022:            written permission, please contact <request_AT_jdom_DOT_org>.
0023:
0024:         4. Products derived from this software may not be called "JDOM", nor
0025:            may "JDOM" appear in their name, without prior written permission
0026:            from the JDOM Project Management <request_AT_jdom_DOT_org>.
0027:
0028:         In addition, we request (but do not require) that you include in the
0029:         end-user documentation provided with the redistribution and/or in the
0030:         software itself an acknowledgement equivalent to the following:
0031:             "This product includes software developed by the
0032:              JDOM Project (http://www.jdom.org/)."
0033:         Alternatively, the acknowledgment may be graphical using the logos
0034:         available at http://www.jdom.org/images/logos.
0035:
0036:         THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0037:         WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0038:         OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039:         DISCLAIMED.  IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
0040:         CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0041:         SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0042:         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0043:         USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0044:         ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0045:         OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0046:         OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0047:         SUCH DAMAGE.
0048:
0049:         This software consists of voluntary contributions made by many
0050:         individuals on behalf of the JDOM Project and was originally
0051:         created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
0052:         Brett McLaughlin <brett_AT_jdom_DOT_org>.  For more information
0053:         on the JDOM Project, please see <http://www.jdom.org/>.
0054:
0055:         */
0056:
0057:        package org.jdom.output;
0058:
0059:        import java.io.*;
0060:        import java.util.*;
0061:
0062:        import javax.xml.transform.Result;
0063:
0064:        import org.jdom.*;
0065:
0066:        /**
0067:         * Outputs a JDOM document as a stream of bytes. The outputter can manage many
0068:         * styles of document formatting, from untouched to pretty printed. The default
0069:         * is to output the document content exactly as created, but this can be changed
0070:         * by setting a new Format object. For pretty-print output, use
0071:         * <code>{@link Format#getPrettyFormat()}</code>. For whitespace-normalized
0072:         * output, use <code>{@link Format#getCompactFormat()}</code>.
0073:         * <p>
0074:         * There are <code>{@link #output output(...)}</code> methods to print any of
0075:         * the standard JDOM classes, including Document and Element, to either a Writer
0076:         * or an OutputStream. <b>Warning</b>: When outputting to a Writer, make sure
0077:         * the writer's encoding matches the encoding setting in the Format object. This
0078:         * ensures the encoding in which the content is written (controlled by the
0079:         * Writer configuration) matches the encoding placed in the document's XML
0080:         * declaration (controlled by the XMLOutputter). Because a Writer cannot be
0081:         * queried for its encoding, the information must be passed to the Format
0082:         * manually in its constructor or via the
0083:         * <code>{@link Format#setEncoding}</code> method. The default encoding is
0084:         * UTF-8.
0085:         * <p>
0086:         * The methods <code>{@link #outputString outputString(...)}</code> are for
0087:         * convenience only; for top performance you should call one of the <code>{@link
0088:         * #output output(...)}</code> methods and pass in your own Writer or
0089:         * OutputStream if possible.
0090:         * <p>
0091:         * XML declarations are always printed on their own line followed by a line
0092:         * seperator (this doesn't change the semantics of the document). To omit
0093:         * printing of the declaration use
0094:         * <code>{@link Format#setOmitDeclaration}</code>. To omit printing of the
0095:         * encoding in the declaration use <code>{@link Format#setOmitEncoding}</code>.
0096:         * Unfortunatly there is currently no way to know the original encoding of the
0097:         * document.
0098:         * <p>
0099:         * Empty elements are by default printed as &lt;empty/&gt;, but this can be
0100:         * configured with <code>{@link Format#setExpandEmptyElements}</code> to cause
0101:         * them to be expanded to &lt;empty&gt;&lt;/empty&gt;.
0102:         *
0103:         * @version $Revision: 1.2 $, $Date: 2005/05/03 07:02:04 $
0104:         * @author  Brett McLaughlin
0105:         * @author  Jason Hunter
0106:         * @author  Jason Reid
0107:         * @author  Wolfgang Werner
0108:         * @author  Elliotte Rusty Harold
0109:         * @author  David &amp; Will (from Post Tool Design)
0110:         * @author  Dan Schaffer
0111:         * @author  Alex Chaffee
0112:         * @author  Bradley S. Huffman
0113:         */
0114:
0115:        public class XMLOutputter implements  Cloneable {
0116:
0117:            private static final String CVS_ID = "@(#) $RCSfile: XMLOutputter.java,v $ $Revision: 1.2 $ $Date: 2005/05/03 07:02:04 $ $Name:  $";
0118:
0119:            // For normal output
0120:            private Format userFormat = Format.getRawFormat();
0121:
0122:            // For xml:space="preserve"
0123:            protected static final Format preserveFormat = Format
0124:                    .getRawFormat();
0125:
0126:            // What's currently in use
0127:            protected Format currentFormat = userFormat;
0128:
0129:            /** Whether output escaping is enabled for the being processed
0130:             * Element - default is <code>true</code> */
0131:            private boolean escapeOutput = true;
0132:
0133:            // * * * * * * * * * * Constructors * * * * * * * * * *
0134:            // * * * * * * * * * * Constructors * * * * * * * * * *
0135:
0136:            /**
0137:             * This will create an <code>XMLOutputter</code> with the default
0138:             * {@link Format} matching {@link Format#getRawFormat}.
0139:             */
0140:            public XMLOutputter() {
0141:            }
0142:
0143:            /**
0144:             * This will create an <code>XMLOutputter</code> with the specified
0145:             * format characteristics.  Note the format object is cloned internally
0146:             * before use.
0147:             */
0148:            public XMLOutputter(Format format) {
0149:                userFormat = (Format) format.clone();
0150:                currentFormat = userFormat;
0151:            }
0152:
0153:            /**
0154:             * This will create an <code>XMLOutputter</code> with all the
0155:             * options as set in the given <code>XMLOutputter</code>.  Note
0156:             * that <code>XMLOutputter two = (XMLOutputter)one.clone();</code>
0157:             * would work equally well.
0158:             *
0159:             * @param that the XMLOutputter to clone
0160:             */
0161:            public XMLOutputter(XMLOutputter that) {
0162:                this .userFormat = (Format) that.userFormat.clone();
0163:                currentFormat = userFormat;
0164:            }
0165:
0166:            // * * * * * * * * * * Set parameters methods * * * * * * * * * *
0167:            // * * * * * * * * * * Set parameters methods * * * * * * * * * *
0168:
0169:            /**
0170:             * Sets the new format logic for the outputter.  Note the Format
0171:             * object is cloned internally before use.
0172:             *
0173:             * @param newFormat the format to use for output
0174:             */
0175:            public void setFormat(Format newFormat) {
0176:                this .userFormat = (Format) newFormat.clone();
0177:                this .currentFormat = userFormat;
0178:            }
0179:
0180:            /**
0181:             * Returns the current format in use by the outputter.  Note the 
0182:             * Format object returned is a clone of the one used internally.
0183:             */
0184:            public Format getFormat() {
0185:                return (Format) userFormat.clone();
0186:            }
0187:
0188:            // * * * * * * * * * * Output to a OutputStream * * * * * * * * * *
0189:            // * * * * * * * * * * Output to a OutputStream * * * * * * * * * *
0190:
0191:            /**
0192:             * This will print the <code>Document</code> to the given output stream.
0193:             * The characters are printed using the encoding specified in the
0194:             * constructor, or a default of UTF-8.
0195:             *
0196:             * @param doc <code>Document</code> to format.
0197:             * @param out <code>OutputStream</code> to use.
0198:             * @throws IOException - if there's any problem writing.
0199:             */
0200:            public void output(Document doc, OutputStream out)
0201:                    throws IOException {
0202:                Writer writer = makeWriter(out);
0203:                output(doc, writer); // output() flushes
0204:            }
0205:
0206:            /**
0207:             * Print out the <code>{@link DocType}</code>.
0208:             *
0209:             * @param doctype <code>DocType</code> to output.
0210:             * @param out <code>OutputStream</code> to use.
0211:             */
0212:            public void output(DocType doctype, OutputStream out)
0213:                    throws IOException {
0214:                Writer writer = makeWriter(out);
0215:                output(doctype, writer); // output() flushes
0216:            }
0217:
0218:            /**
0219:             * Print out an <code>{@link Element}</code>, including
0220:             * its <code>{@link Attribute}</code>s, and all
0221:             * contained (child) elements, etc.
0222:             *
0223:             * @param element <code>Element</code> to output.
0224:             * @param out <code>Writer</code> to use.
0225:             */
0226:            public void output(Element element, OutputStream out)
0227:                    throws IOException {
0228:                Writer writer = makeWriter(out);
0229:                output(element, writer); // output() flushes
0230:            }
0231:
0232:            /**
0233:             * This will handle printing out an <code>{@link
0234:             * Element}</code>'s content only, not including its tag, and
0235:             * attributes.  This can be useful for printing the content of an
0236:             * element that contains HTML, like "&lt;description&gt;JDOM is
0237:             * &lt;b&gt;fun&gt;!&lt;/description&gt;".
0238:             *
0239:             * @param element <code>Element</code> to output.
0240:             * @param out <code>OutputStream</code> to use.
0241:             */
0242:            public void outputElementContent(Element element, OutputStream out)
0243:                    throws IOException {
0244:                Writer writer = makeWriter(out);
0245:                outputElementContent(element, writer); // output() flushes
0246:            }
0247:
0248:            /**
0249:             * This will handle printing out a list of nodes.
0250:             * This can be useful for printing the content of an element that
0251:             * contains HTML, like "&lt;description&gt;JDOM is
0252:             * &lt;b&gt;fun&gt;!&lt;/description&gt;".
0253:             *
0254:             * @param list <code>List</code> of nodes.
0255:             * @param out <code>OutputStream</code> to use.
0256:             */
0257:            public void output(List list, OutputStream out) throws IOException {
0258:                Writer writer = makeWriter(out);
0259:                output(list, writer); // output() flushes
0260:            }
0261:
0262:            /**
0263:             * Print out a <code>{@link CDATA}</code> node.
0264:             *
0265:             * @param cdata <code>CDATA</code> to output.
0266:             * @param out <code>OutputStream</code> to use.
0267:             */
0268:            public void output(CDATA cdata, OutputStream out)
0269:                    throws IOException {
0270:                Writer writer = makeWriter(out);
0271:                output(cdata, writer); // output() flushes
0272:            }
0273:
0274:            /**
0275:             * Print out a <code>{@link Text}</code> node.  Perfoms
0276:             * the necessary entity escaping and whitespace stripping.
0277:             *
0278:             * @param text <code>Text</code> to output.
0279:             * @param out <code>OutputStream</code> to use.
0280:             */
0281:            public void output(Text text, OutputStream out) throws IOException {
0282:                Writer writer = makeWriter(out);
0283:                output(text, writer); // output() flushes
0284:            }
0285:
0286:            /**
0287:             * Print out a <code>{@link Comment}</code>.
0288:             *
0289:             * @param comment <code>Comment</code> to output.
0290:             * @param out <code>OutputStream</code> to use.
0291:             */
0292:            public void output(Comment comment, OutputStream out)
0293:                    throws IOException {
0294:                Writer writer = makeWriter(out);
0295:                output(comment, writer); // output() flushes
0296:            }
0297:
0298:            /**
0299:             * Print out a <code>{@link ProcessingInstruction}</code>.
0300:             *
0301:             * @param pi <code>ProcessingInstruction</code> to output.
0302:             * @param out <code>OutputStream</code> to use.
0303:             */
0304:            public void output(ProcessingInstruction pi, OutputStream out)
0305:                    throws IOException {
0306:                Writer writer = makeWriter(out);
0307:                output(pi, writer); // output() flushes
0308:            }
0309:
0310:            /**
0311:             * Print out a <code>{@link EntityRef}</code>.
0312:             *
0313:             * @param entity <code>EntityRef</code> to output.
0314:             * @param out <code>OutputStream</code> to use.
0315:             */
0316:            public void output(EntityRef entity, OutputStream out)
0317:                    throws IOException {
0318:                Writer writer = makeWriter(out);
0319:                output(entity, writer); // output() flushes
0320:            }
0321:
0322:            /**
0323:             * Get an OutputStreamWriter, using prefered encoding
0324:             * (see {@link Format#setEncoding}).
0325:             */
0326:            private Writer makeWriter(OutputStream out)
0327:                    throws java.io.UnsupportedEncodingException {
0328:                return makeWriter(out, userFormat.encoding);
0329:            }
0330:
0331:            /**
0332:             * Get an OutputStreamWriter, use specified encoding.
0333:             */
0334:            private static Writer makeWriter(OutputStream out, String enc)
0335:                    throws java.io.UnsupportedEncodingException {
0336:                // "UTF-8" is not recognized before JDK 1.1.6, so we'll translate
0337:                // into "UTF8" which works with all JDKs.
0338:                if ("UTF-8".equals(enc)) {
0339:                    enc = "UTF8";
0340:                }
0341:
0342:                Writer writer = new BufferedWriter((new OutputStreamWriter(
0343:                        new BufferedOutputStream(out), enc)));
0344:                return writer;
0345:            }
0346:
0347:            // * * * * * * * * * * Output to a Writer * * * * * * * * * *
0348:            // * * * * * * * * * * Output to a Writer * * * * * * * * * *
0349:
0350:            /**
0351:             * This will print the <code>Document</code> to the given Writer.
0352:             *
0353:             * <p>
0354:             * Warning: using your own Writer may cause the outputter's
0355:             * preferred character encoding to be ignored.  If you use
0356:             * encodings other than UTF-8, we recommend using the method that
0357:             * takes an OutputStream instead.
0358:             * </p>
0359:             *
0360:             * @param doc <code>Document</code> to format.
0361:             * @param out <code>Writer</code> to use.
0362:             * @throws IOException - if there's any problem writing.
0363:             */
0364:            public void output(Document doc, Writer out) throws IOException {
0365:
0366:                printDeclaration(out, doc, userFormat.encoding);
0367:
0368:                // Print out root element, as well as any root level
0369:                // comments and processing instructions,
0370:                // starting with no indentation
0371:                List content = doc.getContent();
0372:                int size = content.size();
0373:                for (int i = 0; i < size; i++) {
0374:                    Object obj = content.get(i);
0375:
0376:                    if (obj instanceof  Element) {
0377:                        printElement(out, doc.getRootElement(), 0,
0378:                                createNamespaceStack());
0379:                    } else if (obj instanceof  Comment) {
0380:                        printComment(out, (Comment) obj);
0381:                    } else if (obj instanceof  ProcessingInstruction) {
0382:                        printProcessingInstruction(out,
0383:                                (ProcessingInstruction) obj);
0384:                    } else if (obj instanceof  DocType) {
0385:                        printDocType(out, doc.getDocType());
0386:                        // Always print line separator after declaration, helps the
0387:                        // output look better and is semantically inconsequential
0388:                        out.write(currentFormat.lineSeparator);
0389:                    } else {
0390:                        // XXX if we get here then we have a illegal content, for
0391:                        //     now we'll just ignore it
0392:                    }
0393:
0394:                    newline(out);
0395:                    indent(out, 0);
0396:                }
0397:
0398:                // Output final line separator
0399:                // We output this no matter what the newline flags say
0400:                out.write(currentFormat.lineSeparator);
0401:
0402:                out.flush();
0403:            }
0404:
0405:            /**
0406:             * Print out the <code>{@link DocType}</code>.
0407:             *
0408:             * @param doctype <code>DocType</code> to output.
0409:             * @param out <code>Writer</code> to use.
0410:             */
0411:            public void output(DocType doctype, Writer out) throws IOException {
0412:                printDocType(out, doctype);
0413:                out.flush();
0414:            }
0415:
0416:            /**
0417:             * Print out an <code>{@link Element}</code>, including
0418:             * its <code>{@link Attribute}</code>s, and all
0419:             * contained (child) elements, etc.
0420:             *
0421:             * @param element <code>Element</code> to output.
0422:             * @param out <code>Writer</code> to use.
0423:             */
0424:            public void output(Element element, Writer out) throws IOException {
0425:                // If this is the root element we could pre-initialize the
0426:                // namespace stack with the namespaces
0427:                printElement(out, element, 0, createNamespaceStack());
0428:                out.flush();
0429:            }
0430:
0431:            /**
0432:             * This will handle printing out an <code>{@link
0433:             * Element}</code>'s content only, not including its tag, and
0434:             * attributes.  This can be useful for printing the content of an
0435:             * element that contains HTML, like "&lt;description&gt;JDOM is
0436:             * &lt;b&gt;fun&gt;!&lt;/description&gt;".
0437:             *
0438:             * @param element <code>Element</code> to output.
0439:             * @param out <code>Writer</code> to use.
0440:             */
0441:            public void outputElementContent(Element element, Writer out)
0442:                    throws IOException {
0443:                List content = element.getContent();
0444:                printContentRange(out, content, 0, content.size(), 0,
0445:                        createNamespaceStack());
0446:                out.flush();
0447:            }
0448:
0449:            /**
0450:             * This will handle printing out a list of nodes.
0451:             * This can be useful for printing the content of an element that
0452:             * contains HTML, like "&lt;description&gt;JDOM is
0453:             * &lt;b&gt;fun&gt;!&lt;/description&gt;".
0454:             *
0455:             * @param list <code>List</code> of nodes.
0456:             * @param out <code>Writer</code> to use.
0457:             */
0458:            public void output(List list, Writer out) throws IOException {
0459:                printContentRange(out, list, 0, list.size(), 0,
0460:                        createNamespaceStack());
0461:                out.flush();
0462:            }
0463:
0464:            /**
0465:             * Print out a <code>{@link CDATA}</code> node.
0466:             *
0467:             * @param cdata <code>CDATA</code> to output.
0468:             * @param out <code>Writer</code> to use.
0469:             */
0470:            public void output(CDATA cdata, Writer out) throws IOException {
0471:                printCDATA(out, cdata);
0472:                out.flush();
0473:            }
0474:
0475:            /**
0476:             * Print out a <code>{@link Text}</code> node.  Perfoms
0477:             * the necessary entity escaping and whitespace stripping.
0478:             *
0479:             * @param text <code>Text</code> to output.
0480:             * @param out <code>Writer</code> to use.
0481:             */
0482:            public void output(Text text, Writer out) throws IOException {
0483:                printText(out, text);
0484:                out.flush();
0485:            }
0486:
0487:            /**
0488:             * Print out a <code>{@link Comment}</code>.
0489:             *
0490:             * @param comment <code>Comment</code> to output.
0491:             * @param out <code>Writer</code> to use.
0492:             */
0493:            public void output(Comment comment, Writer out) throws IOException {
0494:                printComment(out, comment);
0495:                out.flush();
0496:            }
0497:
0498:            /**
0499:             * Print out a <code>{@link ProcessingInstruction}</code>.
0500:             *
0501:             * @param pi <code>ProcessingInstruction</code> to output.
0502:             * @param out <code>Writer</code> to use.
0503:             */
0504:            public void output(ProcessingInstruction pi, Writer out)
0505:                    throws IOException {
0506:                boolean currentEscapingPolicy = currentFormat.ignoreTrAXEscapingPIs;
0507:
0508:                // Output PI verbatim, disregarding TrAX escaping PIs.
0509:                currentFormat.setIgnoreTrAXEscapingPIs(true);
0510:                printProcessingInstruction(out, pi);
0511:                currentFormat.setIgnoreTrAXEscapingPIs(currentEscapingPolicy);
0512:
0513:                out.flush();
0514:            }
0515:
0516:            /**
0517:             * Print out a <code>{@link EntityRef}</code>.
0518:             *
0519:             * @param entity <code>EntityRef</code> to output.
0520:             * @param out <code>Writer</code> to use.
0521:             */
0522:            public void output(EntityRef entity, Writer out) throws IOException {
0523:                printEntityRef(out, entity);
0524:                out.flush();
0525:            }
0526:
0527:            // * * * * * * * * * * Output to a String * * * * * * * * * *
0528:            // * * * * * * * * * * Output to a String * * * * * * * * * *
0529:
0530:            /**
0531:             * Return a string representing a document.  Uses an internal
0532:             * StringWriter. Warning: a String is Unicode, which may not match
0533:             * the outputter's specified encoding.
0534:             *
0535:             * @param doc <code>Document</code> to format.
0536:             */
0537:            public String outputString(Document doc) {
0538:                StringWriter out = new StringWriter();
0539:                try {
0540:                    output(doc, out); // output() flushes
0541:                } catch (IOException e) {
0542:                }
0543:                return out.toString();
0544:            }
0545:
0546:            /**
0547:             * Return a string representing a DocType. Warning: a String is
0548:             * Unicode, which may not match the outputter's specified
0549:             * encoding.
0550:             *
0551:             * @param doctype <code>DocType</code> to format.
0552:             */
0553:            public String outputString(DocType doctype) {
0554:                StringWriter out = new StringWriter();
0555:                try {
0556:                    output(doctype, out); // output() flushes
0557:                } catch (IOException e) {
0558:                }
0559:                return out.toString();
0560:            }
0561:
0562:            /**
0563:             * Return a string representing an element. Warning: a String is
0564:             * Unicode, which may not match the outputter's specified
0565:             * encoding.
0566:             *
0567:             * @param element <code>Element</code> to format.
0568:             */
0569:            public String outputString(Element element) {
0570:                StringWriter out = new StringWriter();
0571:                try {
0572:                    output(element, out); // output() flushes
0573:                } catch (IOException e) {
0574:                }
0575:                return out.toString();
0576:            }
0577:
0578:            /**
0579:             * Return a string representing a list of nodes.  The list is
0580:             * assumed to contain legal JDOM nodes.
0581:             *
0582:             * @param list <code>List</code> to format.
0583:             */
0584:            public String outputString(List list) {
0585:                StringWriter out = new StringWriter();
0586:                try {
0587:                    output(list, out); // output() flushes
0588:                } catch (IOException e) {
0589:                }
0590:                return out.toString();
0591:            }
0592:
0593:            /**
0594:             * Return a string representing a CDATA node. Warning: a String is
0595:             * Unicode, which may not match the outputter's specified
0596:             * encoding.
0597:             *
0598:             * @param cdata <code>CDATA</code> to format.
0599:             */
0600:            public String outputString(CDATA cdata) {
0601:                StringWriter out = new StringWriter();
0602:                try {
0603:                    output(cdata, out); // output() flushes
0604:                } catch (IOException e) {
0605:                }
0606:                return out.toString();
0607:            }
0608:
0609:            /**
0610:             * Return a string representing a Text node. Warning: a String is
0611:             * Unicode, which may not match the outputter's specified
0612:             * encoding.
0613:             *
0614:             * @param text <code>Text</code> to format.
0615:             */
0616:            public String outputString(Text text) {
0617:                StringWriter out = new StringWriter();
0618:                try {
0619:                    output(text, out); // output() flushes
0620:                } catch (IOException e) {
0621:                }
0622:                return out.toString();
0623:            }
0624:
0625:            /**
0626:             * Return a string representing a comment. Warning: a String is
0627:             * Unicode, which may not match the outputter's specified
0628:             * encoding.
0629:             *
0630:             * @param comment <code>Comment</code> to format.
0631:             */
0632:            public String outputString(Comment comment) {
0633:                StringWriter out = new StringWriter();
0634:                try {
0635:                    output(comment, out); // output() flushes
0636:                } catch (IOException e) {
0637:                }
0638:                return out.toString();
0639:            }
0640:
0641:            /**
0642:             * Return a string representing a PI. Warning: a String is
0643:             * Unicode, which may not match the outputter's specified
0644:             * encoding.
0645:             *
0646:             * @param pi <code>ProcessingInstruction</code> to format.
0647:             */
0648:            public String outputString(ProcessingInstruction pi) {
0649:                StringWriter out = new StringWriter();
0650:                try {
0651:                    output(pi, out); // output() flushes
0652:                } catch (IOException e) {
0653:                }
0654:                return out.toString();
0655:            }
0656:
0657:            /**
0658:             * Return a string representing an entity. Warning: a String is
0659:             * Unicode, which may not match the outputter's specified
0660:             * encoding.
0661:             *
0662:             * @param entity <code>EntityRef</code> to format.
0663:             */
0664:            public String outputString(EntityRef entity) {
0665:                StringWriter out = new StringWriter();
0666:                try {
0667:                    output(entity, out); // output() flushes
0668:                } catch (IOException e) {
0669:                }
0670:                return out.toString();
0671:            }
0672:
0673:            // * * * * * * * * * * Internal printing methods * * * * * * * * * *
0674:            // * * * * * * * * * * Internal printing methods * * * * * * * * * *
0675:
0676:            /**
0677:             * This will handle printing of the declaration.
0678:             * Assumes XML version 1.0 since we don't directly know.
0679:             *
0680:             * @param doc <code>Document</code> whose declaration to write.
0681:             * @param out <code>Writer</code> to use.
0682:             * @param encoding The encoding to add to the declaration
0683:             */
0684:            protected void printDeclaration(Writer out, Document doc,
0685:                    String encoding) throws IOException {
0686:
0687:                // Only print the declaration if it's not being omitted
0688:                if (!userFormat.omitDeclaration) {
0689:                    // Assume 1.0 version
0690:                    out.write("<?xml version=\"1.0\"");
0691:                    if (!userFormat.omitEncoding) {
0692:                        out.write(" encoding=\"" + encoding + "\"");
0693:                    }
0694:                    out.write("?>");
0695:
0696:                    // Print new line after decl always, even if no other new lines
0697:                    // Helps the output look better and is semantically
0698:                    // inconsequential
0699:                    out.write(currentFormat.lineSeparator);
0700:                }
0701:            }
0702:
0703:            /**
0704:             * This handle printing the DOCTYPE declaration if one exists.
0705:             *
0706:             * @param docType <code>Document</code> whose declaration to write.
0707:             * @param out <code>Writer</code> to use.
0708:             */
0709:            protected void printDocType(Writer out, DocType docType)
0710:                    throws IOException {
0711:
0712:                String publicID = docType.getPublicID();
0713:                String systemID = docType.getSystemID();
0714:                String internalSubset = docType.getInternalSubset();
0715:                boolean hasPublic = false;
0716:
0717:                out.write("<!DOCTYPE ");
0718:                out.write(docType.getElementName());
0719:                if (publicID != null) {
0720:                    out.write(" PUBLIC \"");
0721:                    out.write(publicID);
0722:                    out.write("\"");
0723:                    hasPublic = true;
0724:                }
0725:                if (systemID != null) {
0726:                    if (!hasPublic) {
0727:                        out.write(" SYSTEM");
0728:                    }
0729:                    out.write(" \"");
0730:                    out.write(systemID);
0731:                    out.write("\"");
0732:                }
0733:                if ((internalSubset != null) && (!internalSubset.equals(""))) {
0734:                    out.write(" [");
0735:                    out.write(currentFormat.lineSeparator);
0736:                    out.write(docType.getInternalSubset());
0737:                    out.write("]");
0738:                }
0739:                out.write(">");
0740:            }
0741:
0742:            /**
0743:             * This will handle printing of comments.
0744:             *
0745:             * @param comment <code>Comment</code> to write.
0746:             * @param out <code>Writer</code> to use.
0747:             */
0748:            protected void printComment(Writer out, Comment comment)
0749:                    throws IOException {
0750:                out.write("<!--");
0751:                out.write(comment.getText());
0752:                out.write("-->");
0753:            }
0754:
0755:            /**
0756:             * This will handle printing of processing instructions.
0757:             *
0758:             * @param pi <code>ProcessingInstruction</code> to write.
0759:             * @param out <code>Writer</code> to use.
0760:             */
0761:            protected void printProcessingInstruction(Writer out,
0762:                    ProcessingInstruction pi) throws IOException {
0763:                String target = pi.getTarget();
0764:                boolean piProcessed = false;
0765:
0766:                if (currentFormat.ignoreTrAXEscapingPIs == false) {
0767:                    if (target.equals(Result.PI_DISABLE_OUTPUT_ESCAPING)) {
0768:                        escapeOutput = false;
0769:                        piProcessed = true;
0770:                    } else if (target.equals(Result.PI_ENABLE_OUTPUT_ESCAPING)) {
0771:                        escapeOutput = true;
0772:                        piProcessed = true;
0773:                    }
0774:                }
0775:                if (piProcessed == false) {
0776:                    String rawData = pi.getData();
0777:
0778:                    // Write <?target data?> or if no data then just <?target?>
0779:                    if (!"".equals(rawData)) {
0780:                        out.write("<?");
0781:                        out.write(target);
0782:                        out.write(" ");
0783:                        out.write(rawData);
0784:                        out.write("?>");
0785:                    } else {
0786:                        out.write("<?");
0787:                        out.write(target);
0788:                        out.write("?>");
0789:                    }
0790:                }
0791:            }
0792:
0793:            /**
0794:             * This will handle printing a <code>{@link EntityRef}</code>.
0795:             * Only the entity reference such as <code>&amp;entity;</code>
0796:             * will be printed. However, subclasses are free to override
0797:             * this method to print the contents of the entity instead.
0798:             *
0799:             * @param entity <code>EntityRef</code> to output.
0800:             * @param out <code>Writer</code> to use.  */
0801:            protected void printEntityRef(Writer out, EntityRef entity)
0802:                    throws IOException {
0803:                out.write("&");
0804:                out.write(entity.getName());
0805:                out.write(";");
0806:            }
0807:
0808:            /**
0809:             * This will handle printing of <code>{@link CDATA}</code> text.
0810:             *
0811:             * @param cdata <code>CDATA</code> to output.
0812:             * @param out <code>Writer</code> to use.
0813:             */
0814:            protected void printCDATA(Writer out, CDATA cdata)
0815:                    throws IOException {
0816:                String str = (currentFormat.mode == Format.TextMode.NORMALIZE) ? cdata
0817:                        .getTextNormalize()
0818:                        : ((currentFormat.mode == Format.TextMode.TRIM) ? cdata
0819:                                .getText().trim() : cdata.getText());
0820:                out.write("<![CDATA[");
0821:                out.write(str);
0822:                out.write("]]>");
0823:            }
0824:
0825:            /**
0826:             * This will handle printing of <code>{@link Text}</code> strings.
0827:             *
0828:             * @param text <code>Text</code> to write.
0829:             * @param out <code>Writer</code> to use.
0830:             */
0831:            protected void printText(Writer out, Text text) throws IOException {
0832:                String str = (currentFormat.mode == Format.TextMode.NORMALIZE) ? text
0833:                        .getTextNormalize()
0834:                        : ((currentFormat.mode == Format.TextMode.TRIM) ? text
0835:                                .getText().trim() : text.getText());
0836:                out.write(escapeElementEntities(str));
0837:            }
0838:
0839:            /**
0840:             * This will handle printing a string.  Escapes the element entities,
0841:             * trims interior whitespace, etc. if necessary.
0842:             */
0843:            private void printString(Writer out, String str) throws IOException {
0844:                if (currentFormat.mode == Format.TextMode.NORMALIZE) {
0845:                    str = Text.normalizeString(str);
0846:                } else if (currentFormat.mode == Format.TextMode.TRIM) {
0847:                    str = str.trim();
0848:                }
0849:                out.write(escapeElementEntities(str));
0850:            }
0851:
0852:            /**
0853:             * This will handle printing of a <code>{@link Element}</code>,
0854:             * its <code>{@link Attribute}</code>s, and all contained (child)
0855:             * elements, etc.
0856:             *
0857:             * @param element <code>Element</code> to output.
0858:             * @param out <code>Writer</code> to use.
0859:             * @param level <code>int</code> level of indention.
0860:             * @param namespaces <code>List</code> stack of Namespaces in scope.
0861:             */
0862:            protected void printElement(Writer out, Element element, int level,
0863:                    NamespaceStack namespaces) throws IOException {
0864:
0865:                List attributes = element.getAttributes();
0866:                List content = element.getContent();
0867:
0868:                // Check for xml:space and adjust format settings
0869:                String space = null;
0870:                if (attributes != null) {
0871:                    space = element.getAttributeValue("space",
0872:                            Namespace.XML_NAMESPACE);
0873:                }
0874:
0875:                Format previousFormat = currentFormat;
0876:
0877:                if ("default".equals(space)) {
0878:                    currentFormat = userFormat;
0879:                } else if ("preserve".equals(space)) {
0880:                    currentFormat = preserveFormat;
0881:                }
0882:
0883:                // Print the beginning of the tag plus attributes and any
0884:                // necessary namespace declarations
0885:                out.write("<");
0886:                printQualifiedName(out, element);
0887:
0888:                // Mark our namespace starting point
0889:                int previouslyDeclaredNamespaces = namespaces.size();
0890:
0891:                // Print the element's namespace, if appropriate
0892:                printElementNamespace(out, element, namespaces);
0893:
0894:                // Print out additional namespace declarations
0895:                printAdditionalNamespaces(out, element, namespaces);
0896:
0897:                // Print out attributes
0898:                if (attributes != null)
0899:                    printAttributes(out, attributes, element, namespaces);
0900:
0901:                // Depending on the settings (newlines, textNormalize, etc), we may
0902:                // or may not want to print all of the content, so determine the
0903:                // index of the start of the content we're interested
0904:                // in based on the current settings.
0905:
0906:                int start = skipLeadingWhite(content, 0);
0907:                int size = content.size();
0908:                if (start >= size) {
0909:                    // Case content is empty or all insignificant whitespace
0910:                    if (currentFormat.expandEmptyElements) {
0911:                        out.write("></");
0912:                        printQualifiedName(out, element);
0913:                        out.write(">");
0914:                    } else {
0915:                        out.write(" />");
0916:                    }
0917:                } else {
0918:                    out.write(">");
0919:
0920:                    // For a special case where the content is only CDATA
0921:                    // or Text we don't want to indent after the start or
0922:                    // before the end tag.
0923:
0924:                    if (nextNonText(content, start) < size) {
0925:                        // Case Mixed Content - normal indentation
0926:                        newline(out);
0927:                        printContentRange(out, content, start, size, level + 1,
0928:                                namespaces);
0929:                        newline(out);
0930:                        indent(out, level);
0931:                    } else {
0932:                        // Case all CDATA or Text - no indentation
0933:                        printTextRange(out, content, start, size);
0934:                    }
0935:                    out.write("</");
0936:                    printQualifiedName(out, element);
0937:                    out.write(">");
0938:                }
0939:
0940:                // remove declared namespaces from stack
0941:                while (namespaces.size() > previouslyDeclaredNamespaces) {
0942:                    namespaces.pop();
0943:                }
0944:
0945:                // Restore our format settings
0946:                currentFormat = previousFormat;
0947:            }
0948:
0949:            /**
0950:             * This will handle printing of content within a given range.
0951:             * The range to print is specified in typical Java fashion; the
0952:             * starting index is inclusive, while the ending index is
0953:             * exclusive.
0954:             *
0955:             * @param content <code>List</code> of content to output
0956:             * @param start index of first content node (inclusive.
0957:             * @param end index of last content node (exclusive).
0958:             * @param out <code>Writer</code> to use.
0959:             * @param level <code>int</code> level of indentation.
0960:             * @param namespaces <code>List</code> stack of Namespaces in scope.
0961:             */
0962:            private void printContentRange(Writer out, List content, int start,
0963:                    int end, int level, NamespaceStack namespaces)
0964:                    throws IOException {
0965:                boolean firstNode; // Flag for 1st node in content
0966:                Object next; // Node we're about to print
0967:                int first, index; // Indexes into the list of content
0968:
0969:                index = start;
0970:                while (index < end) {
0971:                    firstNode = (index == start) ? true : false;
0972:                    next = content.get(index);
0973:
0974:                    //
0975:                    // Handle consecutive CDATA, Text, and EntityRef nodes all at once
0976:                    //
0977:                    if ((next instanceof  Text) || (next instanceof  EntityRef)) {
0978:                        first = skipLeadingWhite(content, index);
0979:                        // Set index to next node for loop
0980:                        index = nextNonText(content, first);
0981:
0982:                        // If it's not all whitespace - print it!
0983:                        if (first < index) {
0984:                            if (!firstNode)
0985:                                newline(out);
0986:                            indent(out, level);
0987:                            printTextRange(out, content, first, index);
0988:                        }
0989:                        continue;
0990:                    }
0991:
0992:                    //
0993:                    // Handle other nodes
0994:                    //
0995:                    if (!firstNode) {
0996:                        newline(out);
0997:                    }
0998:
0999:                    indent(out, level);
1000:
1001:                    if (next instanceof  Comment) {
1002:                        printComment(out, (Comment) next);
1003:                    } else if (next instanceof  Element) {
1004:                        printElement(out, (Element) next, level, namespaces);
1005:                    } else if (next instanceof  ProcessingInstruction) {
1006:                        printProcessingInstruction(out,
1007:                                (ProcessingInstruction) next);
1008:                    } else {
1009:                        // XXX if we get here then we have a illegal content, for
1010:                        //     now we'll just ignore it (probably should throw
1011:                        //     a exception)
1012:                    }
1013:
1014:                    index++;
1015:                } /* while */
1016:            }
1017:
1018:            /**
1019:             * This will handle printing of a sequence of <code>{@link CDATA}</code>
1020:             * or <code>{@link Text}</code> nodes.  It is an error to have any other
1021:             * pass this method any other type of node.
1022:             *
1023:             * @param content <code>List</code> of content to output
1024:             * @param start index of first content node (inclusive).
1025:             * @param end index of last content node (exclusive).
1026:             * @param out <code>Writer</code> to use.
1027:             */
1028:            private void printTextRange(Writer out, List content, int start,
1029:                    int end) throws IOException {
1030:                String previous; // Previous text printed
1031:                Object node; // Next node to print
1032:                String next; // Next text to print
1033:
1034:                previous = null;
1035:
1036:                // Remove leading whitespace-only nodes
1037:                start = skipLeadingWhite(content, start);
1038:
1039:                int size = content.size();
1040:                if (start < size) {
1041:                    // And remove trialing whitespace-only nodes
1042:                    end = skipTrailingWhite(content, end);
1043:
1044:                    for (int i = start; i < end; i++) {
1045:                        node = content.get(i);
1046:
1047:                        // Get the unmangled version of the text
1048:                        // we are about to print
1049:                        if (node instanceof  Text) {
1050:                            next = ((Text) node).getText();
1051:                        } else if (node instanceof  EntityRef) {
1052:                            next = "&" + ((EntityRef) node).getValue() + ";";
1053:                        } else {
1054:                            throw new IllegalStateException("Should see only "
1055:                                    + "CDATA, Text, or EntityRef");
1056:                        }
1057:
1058:                        // This may save a little time
1059:                        if (next == null || "".equals(next)) {
1060:                            continue;
1061:                        }
1062:
1063:                        // Determine if we need to pad the output (padding is
1064:                        // only need in trim or normalizing mode)
1065:                        if (previous != null) { // NotElement 1st node
1066:                            if (currentFormat.mode == Format.TextMode.NORMALIZE
1067:                                    || currentFormat.mode == Format.TextMode.TRIM) {
1068:                                if ((endsWithWhite(previous))
1069:                                        || (startsWithWhite(next))) {
1070:                                    out.write(" ");
1071:                                }
1072:                            }
1073:                        }
1074:
1075:                        // Print the node
1076:                        if (node instanceof  CDATA) {
1077:                            printCDATA(out, (CDATA) node);
1078:                        } else if (node instanceof  EntityRef) {
1079:                            printEntityRef(out, (EntityRef) node);
1080:                        } else {
1081:                            printString(out, next);
1082:                        }
1083:
1084:                        previous = next;
1085:                    }
1086:                }
1087:            }
1088:
1089:            /**
1090:             * This will handle printing of any needed <code>{@link Namespace}</code>
1091:             * declarations.
1092:             *
1093:             * @param ns <code>Namespace</code> to print definition of
1094:             * @param out <code>Writer</code> to use.
1095:             */
1096:            private void printNamespace(Writer out, Namespace ns,
1097:                    NamespaceStack namespaces) throws IOException {
1098:                String prefix = ns.getPrefix();
1099:                String uri = ns.getURI();
1100:
1101:                // Already printed namespace decl?
1102:                if (uri.equals(namespaces.getURI(prefix))) {
1103:                    return;
1104:                }
1105:
1106:                out.write(" xmlns");
1107:                if (!prefix.equals("")) {
1108:                    out.write(":");
1109:                    out.write(prefix);
1110:                }
1111:                out.write("=\"");
1112:                out.write(uri);
1113:                out.write("\"");
1114:                namespaces.push(ns);
1115:            }
1116:
1117:            /**
1118:             * This will handle printing of a <code>{@link Attribute}</code> list.
1119:             *
1120:             * @param attributes <code>List</code> of Attribute objcts
1121:             * @param out <code>Writer</code> to use
1122:             */
1123:            protected void printAttributes(Writer out, List attributes,
1124:                    Element parent, NamespaceStack namespaces)
1125:                    throws IOException {
1126:
1127:                // I do not yet handle the case where the same prefix maps to
1128:                // two different URIs. For attributes on the same element
1129:                // this is illegal; but as yet we don't throw an exception
1130:                // if someone tries to do this
1131:                // Set prefixes = new HashSet();
1132:                for (int i = 0; i < attributes.size(); i++) {
1133:                    Attribute attribute = (Attribute) attributes.get(i);
1134:                    Namespace ns = attribute.getNamespace();
1135:                    if ((ns != Namespace.NO_NAMESPACE)
1136:                            && (ns != Namespace.XML_NAMESPACE)) {
1137:                        printNamespace(out, ns, namespaces);
1138:                    }
1139:
1140:                    out.write(" ");
1141:                    printQualifiedName(out, attribute);
1142:                    out.write("=");
1143:
1144:                    out.write("\"");
1145:                    out.write(escapeAttributeEntities(attribute.getValue()));
1146:                    out.write("\"");
1147:                }
1148:            }
1149:
1150:            private void printElementNamespace(Writer out, Element element,
1151:                    NamespaceStack namespaces) throws IOException {
1152:                // Add namespace decl only if it's not the XML namespace and it's
1153:                // not the NO_NAMESPACE with the prefix "" not yet mapped
1154:                // (we do output xmlns="" if the "" prefix was already used and we
1155:                // need to reclaim it for the NO_NAMESPACE)
1156:                Namespace ns = element.getNamespace();
1157:                if (ns == Namespace.XML_NAMESPACE) {
1158:                    return;
1159:                }
1160:                if (!((ns == Namespace.NO_NAMESPACE) && (namespaces.getURI("") == null))) {
1161:                    printNamespace(out, ns, namespaces);
1162:                }
1163:            }
1164:
1165:            private void printAdditionalNamespaces(Writer out, Element element,
1166:                    NamespaceStack namespaces) throws IOException {
1167:                List list = element.getAdditionalNamespaces();
1168:                if (list != null) {
1169:                    for (int i = 0; i < list.size(); i++) {
1170:                        Namespace additional = (Namespace) list.get(i);
1171:                        printNamespace(out, additional, namespaces);
1172:                    }
1173:                }
1174:            }
1175:
1176:            // * * * * * * * * * * Support methods * * * * * * * * * *
1177:            // * * * * * * * * * * Support methods * * * * * * * * * *
1178:
1179:            /**
1180:             * This will print a new line only if the newlines flag was set to
1181:             * true.
1182:             *
1183:             * @param out <code>Writer</code> to use
1184:             */
1185:            private void newline(Writer out) throws IOException {
1186:                if (currentFormat.indent != null) {
1187:                    out.write(currentFormat.lineSeparator);
1188:                }
1189:            }
1190:
1191:            /**
1192:             * This will print indents (only if the newlines flag was
1193:             * set to <code>true</code>, and indent is non-null).
1194:             *
1195:             * @param out <code>Writer</code> to use
1196:             * @param level current indent level (number of tabs)
1197:             */
1198:            private void indent(Writer out, int level) throws IOException {
1199:                if (currentFormat.indent == null
1200:                        || currentFormat.indent.equals("")) {
1201:                    return;
1202:                }
1203:
1204:                for (int i = 0; i < level; i++) {
1205:                    out.write(currentFormat.indent);
1206:                }
1207:            }
1208:
1209:            // Returns the index of the first non-all-whitespace CDATA or Text,
1210:            // index = content.size() is returned if content contains
1211:            // all whitespace.
1212:            // @param start index to begin search (inclusive)
1213:            private int skipLeadingWhite(List content, int start) {
1214:                if (start < 0) {
1215:                    start = 0;
1216:                }
1217:
1218:                int index = start;
1219:                int size = content.size();
1220:                if (currentFormat.mode == Format.TextMode.TRIM_FULL_WHITE
1221:                        || currentFormat.mode == Format.TextMode.NORMALIZE
1222:                        || currentFormat.mode == Format.TextMode.TRIM) {
1223:                    while (index < size) {
1224:                        if (!isAllWhitespace(content.get(index))) {
1225:                            return index;
1226:                        }
1227:                        index++;
1228:                    }
1229:                }
1230:                return index;
1231:            }
1232:
1233:            // Return the index + 1 of the last non-all-whitespace CDATA or
1234:            // Text node,  index < 0 is returned
1235:            // if content contains all whitespace.
1236:            // @param start index to begin search (exclusive)
1237:            private int skipTrailingWhite(List content, int start) {
1238:                int size = content.size();
1239:                if (start > size) {
1240:                    start = size;
1241:                }
1242:
1243:                int index = start;
1244:                if (currentFormat.mode == Format.TextMode.TRIM_FULL_WHITE
1245:                        || currentFormat.mode == Format.TextMode.NORMALIZE
1246:                        || currentFormat.mode == Format.TextMode.TRIM) {
1247:                    while (index >= 0) {
1248:                        if (!isAllWhitespace(content.get(index - 1)))
1249:                            break;
1250:                        --index;
1251:                    }
1252:                }
1253:                return index;
1254:            }
1255:
1256:            // Return the next non-CDATA, non-Text, or non-EntityRef node,
1257:            // index = content.size() is returned if there is no more non-CDATA,
1258:            // non-Text, or non-EntiryRef nodes
1259:            // @param start index to begin search (inclusive)
1260:            private static int nextNonText(List content, int start) {
1261:                if (start < 0) {
1262:                    start = 0;
1263:                }
1264:
1265:                int index = start;
1266:                int size = content.size();
1267:                while (index < size) {
1268:                    Object node = content.get(index);
1269:                    if (!((node instanceof  Text) || (node instanceof  EntityRef))) {
1270:                        return index;
1271:                    }
1272:                    index++;
1273:                }
1274:                return size;
1275:            }
1276:
1277:            // Determine if a Object is all whitespace
1278:            private boolean isAllWhitespace(Object obj) {
1279:                String str = null;
1280:
1281:                if (obj instanceof  String) {
1282:                    str = (String) obj;
1283:                } else if (obj instanceof  Text) {
1284:                    str = ((Text) obj).getText();
1285:                } else if (obj instanceof  EntityRef) {
1286:                    return false;
1287:                } else {
1288:                    return false;
1289:                }
1290:
1291:                for (int i = 0; i < str.length(); i++) {
1292:                    if (!isWhitespace(str.charAt(i)))
1293:                        return false;
1294:                }
1295:                return true;
1296:            }
1297:
1298:            // Determine if a string starts with a XML whitespace.
1299:            private boolean startsWithWhite(String str) {
1300:                if ((str != null) && (str.length() > 0)
1301:                        && isWhitespace(str.charAt(0))) {
1302:                    return true;
1303:                }
1304:                return false;
1305:            }
1306:
1307:            // Determine if a string ends with a XML whitespace.
1308:            private boolean endsWithWhite(String str) {
1309:                if ((str != null) && (str.length() > 0)
1310:                        && isWhitespace(str.charAt(str.length() - 1))) {
1311:                    return true;
1312:                }
1313:                return false;
1314:            }
1315:
1316:            // Determine if a character is a XML whitespace.
1317:            // XXX should this method be in Verifier
1318:            private static boolean isWhitespace(char c) {
1319:                if (c == ' ' || c == '\n' || c == '\t' || c == '\r') {
1320:                    return true;
1321:                }
1322:                return false;
1323:            }
1324:
1325:            /**
1326:             * This will take the pre-defined entities in XML 1.0 and
1327:             * convert their character representation to the appropriate
1328:             * entity reference, suitable for XML attributes.  It does not convert
1329:             * the single quote (') because it's not necessary as the outputter
1330:             * writes attributes surrounded by double-quotes.
1331:             *
1332:             * @param str <code>String</code> input to escape.
1333:             * @return <code>String</code> with escaped content.
1334:             */
1335:            public String escapeAttributeEntities(String str) {
1336:                StringBuffer buffer;
1337:                char ch;
1338:                String entity;
1339:                EscapeStrategy strategy = currentFormat.escapeStrategy;
1340:
1341:                buffer = null;
1342:                for (int i = 0; i < str.length(); i++) {
1343:                    ch = str.charAt(i);
1344:                    switch (ch) {
1345:                    case '<':
1346:                        entity = "&lt;";
1347:                        break;
1348:                    case '>':
1349:                        entity = "&gt;";
1350:                        break;
1351:                    /*
1352:                     case '\'' :
1353:                     entity = "&apos;";
1354:                     break;
1355:                     */
1356:                    case '\"':
1357:                        entity = "&quot;";
1358:                        break;
1359:                    case '&':
1360:                        entity = "&amp;";
1361:                        break;
1362:                    case '\r':
1363:                        entity = "&#xD;";
1364:                        break;
1365:                    case '\t':
1366:                        entity = "&#x9;";
1367:                        break;
1368:                    case '\n':
1369:                        entity = "&#xA;";
1370:                        break;
1371:                    default:
1372:                        if (strategy.shouldEscape(ch)) {
1373:                            entity = "&#x" + Integer.toHexString(ch) + ";";
1374:                        } else {
1375:                            entity = null;
1376:                        }
1377:                        break;
1378:                    }
1379:                    if (buffer == null) {
1380:                        if (entity != null) {
1381:                            // An entity occurred, so we'll have to use StringBuffer
1382:                            // (allocate room for it plus a few more entities).
1383:                            buffer = new StringBuffer(str.length() + 20);
1384:                            // Copy previous skipped characters and fall through
1385:                            // to pickup current character
1386:                            buffer.append(str.substring(0, i));
1387:                            buffer.append(entity);
1388:                        }
1389:                    } else {
1390:                        if (entity == null) {
1391:                            buffer.append(ch);
1392:                        } else {
1393:                            buffer.append(entity);
1394:                        }
1395:                    }
1396:                }
1397:
1398:                // If there were any entities, return the escaped characters
1399:                // that we put in the StringBuffer. Otherwise, just return
1400:                // the unmodified input string.
1401:                return (buffer == null) ? str : buffer.toString();
1402:            }
1403:
1404:            /**
1405:             * This will take the three pre-defined entities in XML 1.0
1406:             * (used specifically in XML elements) and convert their character
1407:             * representation to the appropriate entity reference, suitable for
1408:             * XML element content.
1409:             *
1410:             * @param str <code>String</code> input to escape.
1411:             * @return <code>String</code> with escaped content.
1412:             */
1413:            public String escapeElementEntities(String str) {
1414:                if (escapeOutput == false)
1415:                    return str;
1416:
1417:                StringBuffer buffer;
1418:                char ch;
1419:                String entity;
1420:                EscapeStrategy strategy = currentFormat.escapeStrategy;
1421:
1422:                buffer = null;
1423:                for (int i = 0; i < str.length(); i++) {
1424:                    ch = str.charAt(i);
1425:                    switch (ch) {
1426:                    case '<':
1427:                        entity = "&lt;";
1428:                        break;
1429:                    case '>':
1430:                        entity = "&gt;";
1431:                        break;
1432:                    case '&':
1433:                        entity = "&amp;";
1434:                        break;
1435:                    case '\r':
1436:                        entity = "&#xD;";
1437:                        break;
1438:                    case '\n':
1439:                        entity = currentFormat.lineSeparator;
1440:                        break;
1441:                    default:
1442:                        if (strategy.shouldEscape(ch)) {
1443:                            entity = "&#x" + Integer.toHexString(ch) + ";";
1444:                        } else {
1445:                            entity = null;
1446:                        }
1447:                        break;
1448:                    }
1449:                    if (buffer == null) {
1450:                        if (entity != null) {
1451:                            // An entity occurred, so we'll have to use StringBuffer
1452:                            // (allocate room for it plus a few more entities).
1453:                            buffer = new StringBuffer(str.length() + 20);
1454:                            // Copy previous skipped characters and fall through
1455:                            // to pickup current character
1456:                            buffer.append(str.substring(0, i));
1457:                            buffer.append(entity);
1458:                        }
1459:                    } else {
1460:                        if (entity == null) {
1461:                            buffer.append(ch);
1462:                        } else {
1463:                            buffer.append(entity);
1464:                        }
1465:                    }
1466:                }
1467:
1468:                // If there were any entities, return the escaped characters
1469:                // that we put in the StringBuffer. Otherwise, just return
1470:                // the unmodified input string.
1471:                return (buffer == null) ? str : buffer.toString();
1472:            }
1473:
1474:            /**
1475:             * Returns a copy of this XMLOutputter.
1476:             */
1477:            public Object clone() {
1478:                // Implementation notes: Since all state of an XMLOutputter is
1479:                // embodied in simple private instance variables, Object.clone
1480:                // can be used.  Note that since Object.clone is totally
1481:                // broken, we must catch an exception that will never be
1482:                // thrown.
1483:                try {
1484:                    return super .clone();
1485:                } catch (java.lang.CloneNotSupportedException e) {
1486:                    // even though this should never ever happen, it's still
1487:                    // possible to fool Java into throwing a
1488:                    // CloneNotSupportedException.  If that happens, we
1489:                    // shouldn't swallow it.
1490:                    throw new RuntimeException(e.toString());
1491:                }
1492:            }
1493:
1494:            /**
1495:             * Return a string listing of the settings for this
1496:             * XMLOutputter instance.
1497:             *
1498:             * @return a string listing the settings for this XMLOutputter instance
1499:             */
1500:            public String toString() {
1501:                StringBuffer buffer = new StringBuffer();
1502:                for (int i = 0; i < userFormat.lineSeparator.length(); i++) {
1503:                    char ch = userFormat.lineSeparator.charAt(i);
1504:                    switch (ch) {
1505:                    case '\r':
1506:                        buffer.append("\\r");
1507:                        break;
1508:                    case '\n':
1509:                        buffer.append("\\n");
1510:                        break;
1511:                    case '\t':
1512:                        buffer.append("\\t");
1513:                        break;
1514:                    default:
1515:                        buffer.append("[" + ((int) ch) + "]");
1516:                        break;
1517:                    }
1518:                }
1519:
1520:                return ("XMLOutputter[omitDeclaration = "
1521:                        + userFormat.omitDeclaration + ", " + "encoding = "
1522:                        + userFormat.encoding + ", " + "omitEncoding = "
1523:                        + userFormat.omitEncoding + ", " + "indent = '"
1524:                        + userFormat.indent + "'" + ", "
1525:                        + "expandEmptyElements = "
1526:                        + userFormat.expandEmptyElements + ", "
1527:                        + "lineSeparator = '" + buffer.toString() + "', "
1528:                        + "textMode = " + userFormat.mode + "]");
1529:            }
1530:
1531:            /**
1532:             * Factory for making new NamespaceStack objects.  The NamespaceStack
1533:             * created is actually an inner class extending the package protected
1534:             * NamespaceStack, as a way to make NamespaceStack "friendly" toward
1535:             * subclassers.
1536:             */
1537:            private NamespaceStack createNamespaceStack() {
1538:                // actually returns a XMLOutputter.NamespaceStack (see below)
1539:                return new NamespaceStack();
1540:            }
1541:
1542:            /**
1543:             * Our own null subclass of NamespaceStack.  This plays a little
1544:             * trick with Java access protection.  We want subclasses of
1545:             * XMLOutputter to be able to override protected methods that
1546:             * declare a NamespaceStack parameter, but we don't want to
1547:             * declare the parent NamespaceStack class as public.
1548:             */
1549:            protected class NamespaceStack extends
1550:                    org.jdom.output.NamespaceStack {
1551:            }
1552:
1553:            // Support method to print a name without using elt.getQualifiedName()
1554:            // and thus avoiding a StringBuffer creation and memory churn
1555:            private void printQualifiedName(Writer out, Element e)
1556:                    throws IOException {
1557:                if (e.getNamespace().getPrefix().length() == 0) {
1558:                    out.write(e.getName());
1559:                } else {
1560:                    out.write(e.getNamespace().getPrefix());
1561:                    out.write(':');
1562:                    out.write(e.getName());
1563:                }
1564:            }
1565:
1566:            // Support method to print a name without using att.getQualifiedName()
1567:            // and thus avoiding a StringBuffer creation and memory churn
1568:            private void printQualifiedName(Writer out, Attribute a)
1569:                    throws IOException {
1570:                String prefix = a.getNamespace().getPrefix();
1571:                if ((prefix != null) && (!prefix.equals(""))) {
1572:                    out.write(prefix);
1573:                    out.write(':');
1574:                    out.write(a.getName());
1575:                } else {
1576:                    out.write(a.getName());
1577:                }
1578:            }
1579:
1580:            // * * * * * * * * * * Deprecated methods * * * * * * * * * *
1581:
1582:            /* The methods below here are deprecations of protected methods.  We
1583:             * don't usually deprecate protected methods, so they're commented out.
1584:             * They're left here in case this mass deprecation causes people trouble.
1585:             * Since we're getting close to 1.0 it's actually better for people to
1586:             * raise issues early though.
1587:             */
1588:
1589:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.