Source Code Cross Referenced for XMLPrinter.java in  » Scripting » Kawa » gnu » xml » 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 » Scripting » Kawa » gnu.xml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // Copyright (c) 2001, 2003, 2005, 2006  Per M.A. Bothner and Brainfood Inc.
002:        // This is free software;  for terms and warranty disclaimer see ./COPYING.
003:
004:        package gnu.xml;
005:
006:        import gnu.lists.*;
007:        import java.io.*;
008:        import gnu.text.*;
009:        import gnu.math.RealNum;
010:        import gnu.text.PrettyWriter;
011:        import gnu.mapping.OutPort;
012:        import gnu.mapping.ThreadLocation;
013:        import gnu.mapping.Symbol;
014:        import java.math.BigDecimal;
015:        import gnu.expr.Keyword;
016:        import gnu.kawa.xml.XmlNamespace;
017:
018:        /** Print an event stream in XML format on a PrintWriter. */
019:
020:        public class XMLPrinter extends OutPort implements  PositionConsumer,
021:                XConsumer {
022:            /** Controls whether to add extra indentation.
023:             * -1: don't add indentation; 0: pretty-print (avoid needless newlines);
024:             * 1: indent (force). */
025:            public int printIndent = -1;
026:            /** When indentating, should attributes be lined up? */
027:            public boolean indentAttributes;
028:
029:            boolean printXMLdecl = false;
030:
031:            public void setPrintXMLdecl(boolean value) {
032:                printXMLdecl = value;
033:            }
034:
035:            boolean inDocument;
036:            boolean inAttribute = false;
037:            boolean inStartTag = false;
038:            /** 0: not in comment; 1: in comment normal; 2: in comment after '-'. */
039:            int inComment;
040:            boolean needXMLdecl = false;
041:            boolean canonicalize = true;
042:            public boolean canonicalizeCDATA;
043:            /** Handling of empty elements.
044:             * 0: No element element tags, as required for canonical XML:
045:             * {@code <br></br>}.
046:             * 1: Use XML-style empty element tags: {@code <br/>}
047:             * 2: Use HTML-compatible empty element tags: {@code <br />}
048:             */
049:            public int useEmptyElementTag = 2;
050:            public boolean escapeText = true;
051:            public boolean escapeNonAscii = true;
052:            boolean isHtml = false;
053:            boolean undeclareNamespaces = false;
054:            Object style;
055:            /** Fluid parameter to control whether a DOCTYPE declaration is emitted.
056:             * If non-null, this is the the public identifier. */
057:            public static final ThreadLocation doctypeSystem = new ThreadLocation(
058:                    "doctype-system");
059:            /** The system identifier emitted in a DOCTYPE declaration. 
060:             * Has no effect if doctypeSystem returns null.
061:             * If non-null, this is the the system identifier. */
062:            public static final ThreadLocation doctypePublic = new ThreadLocation(
063:                    "doctype-public");
064:            public static final ThreadLocation indentLoc = new ThreadLocation(
065:                    "xml-indent");
066:
067:            public boolean strict;
068:
069:            /** Chain of currently active namespace nodes. */
070:            NamespaceBinding namespaceBindings = NamespaceBinding.predefinedXML;
071:
072:            /** Stack of namespaceBindings as of active startElement calls. */
073:            NamespaceBinding[] namespaceSaveStack = new NamespaceBinding[20];
074:
075:            Object[] elementNameStack = new Object[20];
076:
077:            /** Difference between number of startElement and endElement calls so far. */
078:            int elementNesting;
079:
080:            /* If prev==WORD, last output was a number or similar. */
081:            private static final int WORD = -2;
082:            private static final int ELEMENT_START = -3;
083:            private static final int ELEMENT_END = -4;
084:            private static final int COMMENT = -5;
085:            private static final int KEYWORD = -6;
086:            int prev = ' ';
087:
088:            char savedHighSurrogate; // should perhaps be combined with prev?
089:
090:            public XMLPrinter(OutPort out, boolean autoFlush) {
091:                super (out, autoFlush);
092:            }
093:
094:            public XMLPrinter(Writer out, boolean autoFlush) {
095:                super (out, autoFlush);
096:            }
097:
098:            public XMLPrinter(OutputStream out, boolean autoFlush) {
099:                super (new OutputStreamWriter(out), true, autoFlush);
100:            }
101:
102:            public XMLPrinter(Writer out) {
103:                super (out);
104:            }
105:
106:            public XMLPrinter(OutputStream out) {
107:                super (new OutputStreamWriter(out), false, false);
108:            }
109:
110:            public XMLPrinter(OutputStream out, Path path) {
111:                super (new OutputStreamWriter(out), true, false, path);
112:            }
113:
114:            public static XMLPrinter make(OutPort out, Object style) {
115:                XMLPrinter xout = new XMLPrinter(out, true);
116:                xout.setStyle(style);
117:                return xout;
118:            }
119:
120:            /** Convert argument to string in XML syntax. */
121:
122:            public static String toString(Object value) {
123:                StringWriter stringWriter = new StringWriter();
124:                new XMLPrinter(stringWriter).writeObject(value);
125:                return stringWriter.toString();
126:            }
127:
128:            public void setStyle(Object style) {
129:                this .style = style;
130:                useEmptyElementTag = canonicalize ? 0 : 1;
131:                if ("html".equals(style)) {
132:                    isHtml = true;
133:                    useEmptyElementTag = 2;
134:                    // Pre-establish the html namespace, so it doesn't get printed.
135:                    if (namespaceBindings == NamespaceBinding.predefinedXML)
136:                        namespaceBindings = XmlNamespace.HTML_BINDINGS;
137:                } else if (namespaceBindings == XmlNamespace.HTML_BINDINGS)
138:                    namespaceBindings = NamespaceBinding.predefinedXML;
139:                if ("xhtml".equals(style))
140:                    useEmptyElementTag = 2;
141:                if ("plain".equals(style))
142:                    escapeText = false;
143:            }
144:
145:            boolean mustHexEscape(int v) {
146:                return (v >= 127 && (v <= 159 || escapeNonAscii))
147:                        || v == 0x2028
148:                        // We must escape control characters in attributes,
149:                        // since otherwise they get normalized to ' '.
150:                        || (v < ' ' && (inAttribute || (v != '\t' && v != '\n')));
151:            }
152:
153:            public void write(int v) {
154:                closeTag();
155:                if (printIndent >= 0) {
156:                    if ((v == '\r' || v == '\n')) {
157:                        if (v != '\n' || prev != '\r')
158:                            writeBreak(PrettyWriter.NEWLINE_MANDATORY);
159:                        if (inComment > 0)
160:                            inComment = 1;
161:                        return;
162:                    }
163:                }
164:                if (!escapeText) {
165:                    bout.write(v);
166:                    prev = v;
167:                } else if (inComment > 0) {
168:                    if (v == '-') {
169:                        if (inComment == 1)
170:                            inComment = 2;
171:                        else
172:                            bout.write(' ');
173:                    } else
174:                        inComment = 1;
175:                    super .write(v);
176:                } else {
177:                    prev = ';';
178:                    if (v == '<' && !(isHtml && inAttribute))
179:                        bout.write("&lt;");
180:                    else if (v == '>')
181:                        bout.write("&gt;");
182:                    else if (v == '&')
183:                        bout.write("&amp;");
184:                    else if (v == '\"' && inAttribute)
185:                        bout.write("&quot;");
186:                    else if (mustHexEscape(v)) {
187:                        int i = v;
188:                        if (v >= 0xD800) {
189:                            if (v < 0xDC00) {
190:                                savedHighSurrogate = (char) v;
191:                                return;
192:                            } else if (v < 0xE000) { // low surrogate
193:                                //if (highSurrogate < 0xDC00 || highSurrogate > 0xE000)
194:                                // error();
195:                                i = (savedHighSurrogate - 0xD800) * 0x400
196:                                        + (i - 0xDC00) + 0x10000;
197:                                savedHighSurrogate = 0;
198:                            }
199:                        }
200:                        bout.write("&#x" + Integer.toHexString(i).toUpperCase()
201:                                + ";");
202:                    } else {
203:                        bout.write(v);
204:                        prev = v;
205:                    }
206:                }
207:            }
208:
209:            private void startWord() {
210:                closeTag();
211:                writeWordStart();
212:            }
213:
214:            public void writeBoolean(boolean v) {
215:                startWord();
216:                super .print(v);
217:                writeWordEnd();
218:            }
219:
220:            protected void startNumber() {
221:                startWord();
222:            }
223:
224:            protected void endNumber() {
225:                writeWordEnd();
226:            }
227:
228:            public void closeTag() {
229:                if (inStartTag && !inAttribute) {
230:                    if (printIndent >= 0 && indentAttributes)
231:                        endLogicalBlock("");
232:                    bout.write('>');
233:                    inStartTag = false;
234:                    prev = ELEMENT_START;
235:                } else if (needXMLdecl) {
236:                    // should also include encoding declaration FIXME.
237:                    bout.write("<?xml version=\"1.0\"?>\n");
238:                    if (printIndent >= 0) {
239:                        startLogicalBlock("", "", 2);
240:                    }
241:                    needXMLdecl = false;
242:                }
243:            }
244:
245:            void setIndentMode() {
246:                Object xmlIndent = indentLoc.get(null);
247:                String indent = xmlIndent == null ? null : xmlIndent.toString();
248:                if (indent == null)
249:                    printIndent = -1;
250:                else if (indent.equals("pretty"))
251:                    printIndent = 0;
252:                else if (indent.equals("always") || indent.equals("yes"))
253:                    printIndent = 1;
254:                else
255:                    // if (ident.equals("no")) or default:
256:                    printIndent = -1;
257:            }
258:
259:            public void startDocument() {
260:                if (printXMLdecl) {
261:                    // We should emit an XML declaration, but don't emit it yet, in case
262:                    // we get it later as a processing instruction.
263:                    needXMLdecl = true;
264:                }
265:                setIndentMode();
266:                inDocument = true;
267:                if (printIndent >= 0 && !needXMLdecl)
268:                    startLogicalBlock("", "", 2);
269:            }
270:
271:            public void endDocument() {
272:                inDocument = false;
273:                if (printIndent >= 0)
274:                    endLogicalBlock("");
275:                freshLine();
276:            }
277:
278:            public void beginEntity(Object base) {
279:            }
280:
281:            public void endEntity() {
282:            }
283:
284:            protected void writeQName(Object name) {
285:                if (name instanceof  Symbol) {
286:                    Symbol sname = (Symbol) name;
287:                    String prefix = sname.getPrefix();
288:                    if (prefix != null && prefix.length() > 0) {
289:                        bout.write(prefix);
290:                        bout.write(':');
291:                    }
292:                    bout.write(sname.getLocalPart());
293:                } else
294:                    bout.write(name == null ? "{null name}" : (String) name);
295:            }
296:
297:            public void startElement(Object type) {
298:                closeTag();
299:                if (elementNesting == 0) {
300:                    if (!inDocument)
301:                        setIndentMode();
302:                    Object systemIdentifier = doctypeSystem.get(null);
303:                    if (systemIdentifier != null) {
304:                        String systemId = systemIdentifier.toString();
305:                        if (systemId.length() > 0) {
306:                            Object publicIdentifier = doctypePublic.get(null);
307:                            bout.write("<!DOCTYPE ");
308:                            bout.write(type.toString());
309:                            String publicId = publicIdentifier == null ? null
310:                                    : publicIdentifier.toString();
311:                            if (publicId != null && publicId.length() > 0) {
312:                                bout.write(" PUBLIC \"");
313:                                bout.write(publicId);
314:                                bout.write("\" \"");
315:                            } else {
316:                                bout.write(" SYSTEM \"");
317:                            }
318:                            bout.write(systemId);
319:                            bout.write("\">");
320:                            println();
321:                        }
322:                    }
323:                }
324:                if (printIndent >= 0) {
325:                    if (prev == ELEMENT_START || prev == ELEMENT_END
326:                            || prev == COMMENT)
327:                        writeBreak(printIndent > 0 ? PrettyWriter.NEWLINE_MANDATORY
328:                                : PrettyWriter.NEWLINE_LINEAR);
329:                    startLogicalBlock("", "", 2);
330:                }
331:                bout.write('<');
332:                writeQName(type);
333:                if (printIndent >= 0 && indentAttributes)
334:                    startLogicalBlock("", "", 2);
335:                elementNameStack[elementNesting] = type;
336:                NamespaceBinding elementBindings = null;
337:                namespaceSaveStack[elementNesting++] = namespaceBindings;
338:                if (type instanceof  XName) {
339:                    elementBindings = ((XName) type).namespaceNodes;
340:                    NamespaceBinding join = NamespaceBinding.commonAncestor(
341:                            elementBindings, namespaceBindings);
342:                    int numBindings = elementBindings == null ? 0
343:                            : elementBindings.count(join);
344:                    NamespaceBinding[] sortedBindings = new NamespaceBinding[numBindings];
345:                    int i = 0;
346:                    boolean sortNamespaces = canonicalize;
347:                    check_namespaces: for (NamespaceBinding ns = elementBindings; ns != join; ns = ns.next) {
348:                        int j = i;
349:                        boolean skip = false;
350:                        String uri = ns.getUri();
351:                        String prefix = ns.getPrefix();
352:                        while (--j >= 0) {
353:                            NamespaceBinding ns_j = sortedBindings[j];
354:                            // If (compare(ns, ns_j) <= 0) break:
355:                            String prefix_j = ns_j.getPrefix();
356:                            if (prefix == prefix_j)
357:                                continue check_namespaces;
358:                            // If we're not canonicalizing, we just want to suppress
359:                            // duplicates, rather than putting them in order.
360:                            // Note we put the bindings in reverse order, since that's
361:                            // the following print loop expects.
362:                            if (!sortNamespaces)
363:                                continue;
364:                            if (prefix == null)
365:                                break;
366:                            if (prefix_j != null
367:                                    && prefix.compareTo(prefix_j) <= 0)
368:                                break;
369:                            sortedBindings[j + 1] = ns_j;
370:                        }
371:                        if (sortNamespaces)
372:                            j++;
373:                        else
374:                            j = i;
375:                        sortedBindings[j] = ns;
376:                        i++;
377:                    }
378:                    numBindings = i;
379:                    // Note we print the bindings in reverse order, since the chain
380:                    // is in reverse document order.
381:                    for (i = numBindings; --i >= 0;) {
382:                        NamespaceBinding ns = sortedBindings[i];
383:                        String prefix = ns.prefix;
384:                        String uri = ns.uri;
385:                        if (uri == namespaceBindings.resolve(prefix))
386:                            // A matching namespace declaration is already in scope.
387:                            continue;
388:                        if (uri == null && prefix != null
389:                                && !undeclareNamespaces)
390:                            continue;
391:                        bout.write(' '); // prettyprint break
392:                        if (prefix == null)
393:                            bout.write("xmlns");
394:                        else {
395:                            bout.write("xmlns:");
396:                            bout.write(prefix);
397:                        }
398:                        bout.write("=\"");
399:                        inAttribute = true;
400:                        if (uri != null)
401:                            write(uri);
402:                        inAttribute = false;
403:                        bout.write('\"');
404:                    }
405:                    if (undeclareNamespaces) {
406:                        // As needed emit namespace undeclarations as in
407:                        // the XML Namespaces 1.1 Candidate Recommendation.
408:                        // Most commonly this loop will run zero times.
409:                        for (NamespaceBinding ns = namespaceBindings; ns != join; ns = ns.next) {
410:                            String prefix = ns.prefix;
411:                            if (ns.uri != null
412:                                    && elementBindings.resolve(prefix) == null) {
413:                                bout.write(' '); // prettyprint break
414:                                if (prefix == null)
415:                                    bout.write("xmlns");
416:                                else {
417:                                    bout.write("xmlns:");
418:                                    bout.write(prefix);
419:                                }
420:                                bout.write("=\"\"");
421:                            }
422:                        }
423:                    }
424:                    namespaceBindings = elementBindings;
425:                }
426:                if (elementNesting >= namespaceSaveStack.length) {
427:                    NamespaceBinding[] nstmp = new NamespaceBinding[2 * elementNesting];
428:                    System.arraycopy(namespaceSaveStack, 0, nstmp, 0,
429:                            elementNesting);
430:                    namespaceSaveStack = nstmp;
431:                    Object[] nmtmp = new Object[2 * elementNesting];
432:                    System.arraycopy(elementNameStack, 0, nmtmp, 0,
433:                            elementNesting);
434:                    elementNameStack = nmtmp;
435:                }
436:
437:                inStartTag = true;
438:                if (isHtml) {
439:                    String typeName = (type instanceof  Symbol ? ((Symbol) type)
440:                            .getLocalPart() : type.toString());
441:                    if ("script".equals(typeName) || "style".equals(typeName))
442:                        escapeText = false;
443:                }
444:            }
445:
446:            static final String HtmlEmptyTags = "/area/base/basefont/br/col/frame/hr/img/input/isindex/link/meta/para/";
447:
448:            public static boolean isHtmlEmptyElementTag(String name) {
449:                int index = HtmlEmptyTags.indexOf(name);
450:                return index > 0 && HtmlEmptyTags.charAt(index - 1) == '/'
451:                        && HtmlEmptyTags.charAt(index + name.length()) == '/';
452:            }
453:
454:            public void endElement() {
455:                if (useEmptyElementTag == 0)
456:                    closeTag();
457:                Object type = elementNameStack[elementNesting - 1];
458:                String typeName = !isHtml ? null // not needed
459:                        : type instanceof  Symbol ? ((Symbol) type)
460:                                .getLocalPart() : type.toString();
461:                if (inStartTag) {
462:                    if (printIndent >= 0 && indentAttributes) {
463:                        endLogicalBlock("");
464:                    }
465:                    bout.write(isHtml ? (isHtmlEmptyElementTag(typeName) ? ">"
466:                            : "></" + typeName + ">")
467:                            : (useEmptyElementTag == 2 ? " />" : "/>"));
468:                    inStartTag = false;
469:                } else {
470:                    if (printIndent >= 0) {
471:                        setIndentation(0, false);
472:                        if (prev == ELEMENT_END)
473:                            writeBreak(printIndent > 0 ? PrettyWriter.NEWLINE_MANDATORY
474:                                    : PrettyWriter.NEWLINE_LINEAR);
475:                    }
476:                    bout.write("</");
477:                    writeQName(type);
478:                    bout.write(">");
479:                }
480:                if (printIndent >= 0) {
481:                    endLogicalBlock("");
482:                }
483:                prev = ELEMENT_END;
484:                if (isHtml
485:                        && !escapeText
486:                        && ("script".equals(typeName) || "style"
487:                                .equals(typeName)))
488:                    escapeText = true;
489:
490:                namespaceBindings = namespaceSaveStack[--elementNesting];
491:                namespaceSaveStack[elementNesting] = null;
492:                elementNameStack[elementNesting] = null;
493:            }
494:
495:            /** Write a attribute for the current element.
496:             * This is only allowed immediately after a startElement. */
497:            public void startAttribute(Object attrType) {
498:                if (!inStartTag && strict)
499:                    error("attribute not in element", "SENR0001");
500:                if (inAttribute)
501:                    bout.write('"');
502:                inAttribute = true;
503:                bout.write(' ');
504:                if (printIndent >= 0)
505:                    writeBreakFill();
506:                bout.write(attrType.toString()); // FIXME: use Symbol.print
507:                bout.write("=\"");
508:                prev = ' ';
509:            }
510:
511:            public void endAttribute() {
512:                if (inAttribute) {
513:                    if (prev != KEYWORD) {
514:                        bout.write('"');
515:                        inAttribute = false;
516:                    }
517:                    prev = ' ';
518:                }
519:            }
520:
521:            public void writeDouble(double d) {
522:                startWord();
523:                bout.write(formatDouble(d));
524:            }
525:
526:            public void writeFloat(float f) {
527:                startWord();
528:                bout.write(formatFloat(f));
529:            }
530:
531:            /** Helper to format xs:double according to XPath/XQuery specification. */
532:            public static String formatDouble(double d) {
533:                if (Double.isNaN(d))
534:                    return "NaN";
535:                boolean neg = d < 0;
536:                if (Double.isInfinite(d))
537:                    return neg ? "-INF" : "INF";
538:                double dabs = neg ? -d : d;
539:                String dstr = Double.toString(d);
540:                // Unfortunately, XQuery's rules for when to use scientific notation
541:                // are different from Java's.  So fixup the string, if needed.
542:                if ((dabs >= 1000000 || dabs < 0.000001) && dabs != 0.0)
543:                    return RealNum.toStringScientific(dstr);
544:                else
545:                    return formatDecimal(RealNum.toStringDecimal(dstr));
546:            }
547:
548:            /** Helper to format xs:float according to XPath/XQuery specification. */
549:            public static String formatFloat(float f) {
550:                if (Float.isNaN(f))
551:                    return "NaN";
552:                boolean neg = f < 0;
553:                if (Float.isInfinite(f))
554:                    return neg ? "-INF" : "INF";
555:                float fabs = neg ? -f : f;
556:                String fstr = Float.toString(f);
557:                // Unfortunately, XQuery's rules for when to use scientific notation
558:                // are different from Java's.  So fixup the string, if needed.
559:                if ((fabs >= 1000000 || fabs < 0.000001) && fabs != 0.0)
560:                    return RealNum.toStringScientific(fstr);
561:                else
562:                    return formatDecimal(RealNum.toStringDecimal(fstr));
563:            }
564:
565:            /** Format java.math.BigDecimal as needed for XPath/XQuery's xs:decimal.
566:             * Specifically this means removing trailing fractional zeros, and a trailing
567:             * decimal point. However, note that the XML Schema canonical representation
568:             * does require a decimal point and at least one fractional digit.
569:             */
570:            public static String formatDecimal(BigDecimal dec) {
571:                /* #ifdef JAVA5 */
572:                // return formatDecimal(dec.toPlainString());
573:                /* #else */
574:                return formatDecimal(dec.toString());
575:                /* #endif */
576:            }
577:
578:            static String formatDecimal(String str) {
579:                int dot = str.indexOf('.');
580:                if (dot >= 0) {
581:                    int len = str.length();
582:                    for (int pos = len;;) {
583:                        char ch = str.charAt(--pos);
584:                        if (ch != '0') {
585:                            if (ch != '.')
586:                                pos++;
587:                            return pos == len ? str : str.substring(0, pos);
588:                        }
589:                    }
590:                }
591:                return str;
592:            }
593:
594:            public void print(Object v) {
595:                if (v instanceof  BigDecimal)
596:                    v = formatDecimal((BigDecimal) v);
597:                else if (v instanceof  Double || v instanceof  gnu.math.DFloNum)
598:                    v = formatDouble(((Number) v).doubleValue());
599:                else if (v instanceof  Float)
600:                    v = formatFloat(((Float) v).floatValue());
601:                write(v == null ? "(null)" : v.toString());
602:            }
603:
604:            public void writeObject(Object v) {
605:                if (v instanceof  SeqPosition) {
606:                    bout.clearWordEnd();
607:                    SeqPosition pos = (SeqPosition) v;
608:                    pos.sequence.consumeNext(pos.ipos, this );
609:                    if (pos.sequence instanceof  NodeTree)
610:                        prev = '-';
611:                    return;
612:                }
613:                if (v instanceof  Consumable && !(v instanceof  UnescapedData)) {
614:                    ((Consumable) v).consume(this );
615:                    return;
616:                }
617:                if (v instanceof  Keyword) {
618:                    startAttribute(((Keyword) v).getName());
619:                    prev = KEYWORD;
620:                    return;
621:                }
622:                closeTag();
623:                if (v instanceof  UnescapedData) {
624:                    bout.clearWordEnd();
625:                    bout.write(((UnescapedData) v).getData());
626:                    prev = '-';
627:                } else if (v instanceof  Char)
628:                    Char.print(((Char) v).intValue(), this );
629:                else {
630:                    startWord();
631:                    prev = ' ';
632:                    print(v);
633:                    writeWordEnd();
634:                    prev = WORD;
635:                }
636:            }
637:
638:            /** Write each element of a sequence, which can be an array,
639:             * a Sequence or a Consumable. */
640:            //public void writeAll(Object sequence);
641:            /** True if consumer is ignoring rest of element.
642:             * The producer can use this information to skip ahead. */
643:            public boolean ignoring() {
644:                return false;
645:            }
646:
647:            public void write(String str, int start, int length) {
648:                if (length > 0) {
649:                    closeTag();
650:                    int limit = start + length;
651:                    int count = 0;
652:                    while (start < limit) {
653:                        char c = str.charAt(start++);
654:                        if (mustHexEscape(c)
655:                                || (inComment > 0 ? (c == '-' || inComment == 2)
656:                                        : (c == '<' || c == '>' || c == '&' || (inAttribute && (c == '"' || c < ' '))))) {
657:                            if (count > 0)
658:                                bout.write(str, start - 1 - count, count);
659:                            write(c);
660:                            count = 0;
661:                        } else
662:                            count++;
663:                    }
664:                    if (count > 0)
665:                        bout.write(str, limit - count, count);
666:                }
667:                prev = '-';
668:            }
669:
670:            public void write(char[] buf, int off, int len) {
671:                if (len > 0) {
672:                    closeTag();
673:                    int limit = off + len;
674:                    int count = 0;
675:                    while (off < limit) {
676:                        char c = buf[off++];
677:                        if (mustHexEscape(c)
678:                                || (inComment > 0 ? (c == '-' || inComment == 2)
679:                                        : (c == '<' || c == '>' || c == '&' || (inAttribute && (c == '"' || c < ' '))))) {
680:                            if (count > 0)
681:                                bout.write(buf, off - 1 - count, count);
682:                            write(c);
683:                            count = 0;
684:                        } else
685:                            count++;
686:                    }
687:                    if (count > 0)
688:                        bout.write(buf, limit - count, count);
689:                }
690:                prev = '-';
691:            }
692:
693:            public void writePosition(AbstractSequence seq, int ipos) {
694:                seq.consumeNext(ipos, this );
695:            }
696:
697:            public void writeBaseUri(Object uri) {
698:            }
699:
700:            public void beginComment() {
701:                closeTag();
702:                if (printIndent >= 0) {
703:                    if (prev == ELEMENT_START || prev == ELEMENT_END
704:                            || prev == COMMENT)
705:                        writeBreak(printIndent > 0 ? PrettyWriter.NEWLINE_MANDATORY
706:                                : PrettyWriter.NEWLINE_LINEAR);
707:                }
708:                bout.write("<!--");
709:                inComment = 1;
710:            }
711:
712:            public void endComment() {
713:                bout.write("-->");
714:                prev = COMMENT;
715:                inComment = 0;
716:            }
717:
718:            public void writeComment(String chars) {
719:                beginComment();
720:                write(chars);
721:                endComment();
722:            }
723:
724:            public void writeComment(char[] chars, int offset, int length) {
725:                beginComment();
726:                write(chars, offset, length);
727:                endComment();
728:            }
729:
730:            public void writeCDATA(char[] chars, int offset, int length) {
731:                if (canonicalizeCDATA) {
732:                    write(chars, offset, length);
733:                    return;
734:                }
735:                closeTag();
736:                bout.write("<![CDATA[");
737:                int limit = offset + length;
738:                // Look for and deal with embedded "]]>".  This can't happen with
739:                // data generated from XML, but maybe somebody generated invalid CDATA.
740:                for (int i = offset; i < limit - 2; i++) {
741:                    if (chars[i] == ']' && chars[i + 1] == ']'
742:                            && chars[i + 2] == '>') {
743:                        if (i > offset)
744:                            bout.write(chars, offset, i - offset);
745:                        print("]]]><![CDATA[]>");
746:                        offset = i + 3;
747:                        length = limit - offset;
748:                        i = i + 2;
749:                    }
750:                }
751:                bout.write(chars, offset, length);
752:                bout.write("]]>");
753:                prev = '>';
754:            }
755:
756:            public void writeProcessingInstruction(String target,
757:                    char[] content, int offset, int length) {
758:                if ("xml".equals(target))
759:                    needXMLdecl = false;
760:                closeTag();
761:                bout.write("<?");
762:                print(target);
763:                print(' ');
764:                bout.write(content, offset, length);
765:                bout.write("?>");
766:                prev = '>';
767:            }
768:
769:            public void consume(SeqPosition position) {
770:                position.sequence.consumeNext(position.ipos, this );
771:            }
772:
773:            public void error(String msg, String code) {
774:                throw new RuntimeException("serialization error: " + msg + " ["
775:                        + code + ']');
776:            }
777:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.