Java tutorial
/* * Copyright * 2007 axYus - www.axyus.com * 2007 C.Marchand - christophe.marchand@axyus.com * * This file is part of XEMELIOS. * * XEMELIOS is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * XEMELIOS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with XEMELIOS; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package fr.gouv.finances.dgfip.xemelios.utils; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringWriter; import java.io.Writer; import org.apache.commons.lang.StringEscapeUtils; import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.DocumentFragment; import org.w3c.dom.DocumentType; import org.w3c.dom.Element; import org.w3c.dom.Entity; import org.w3c.dom.EntityReference; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Notation; import org.w3c.dom.ProcessingInstruction; import org.w3c.dom.Text; /** * TextWriter takes a Document, DocumentFragment, or Element and streams it * as text or HTML to an output source (or a String) * */ public final class TextWriter { private static final String DefaultIndentBuffer; private String defaultEncoding = "ISO-8859-1"; static { StringBuffer sb = new StringBuffer(256); for (int i = 0; i < 256; i++) sb.append(' '); DefaultIndentBuffer = sb.toString(); } private Node node; private boolean produceHTML; private boolean prettyPrint; private int indentSize = 4; private int indentLevel = 0; private String indentTemplate = DefaultIndentBuffer; private StringBuffer textBuffer = new StringBuffer(); public TextWriter(Node node, boolean produceHTML, boolean prettyPrint, int indentSize) { this.node = node; this.produceHTML = produceHTML; this.prettyPrint = prettyPrint; this.indentSize = indentSize; } public TextWriter(Node node, boolean produceHTML, boolean prettyPrint) { this.node = node; this.produceHTML = produceHTML; this.prettyPrint = prettyPrint; } public TextWriter(Node node, boolean produceHTML) { this.node = node; this.produceHTML = produceHTML; } public TextWriter(Node node) { this.node = node; } public TextWriter(Node node, String encoding) { this.node = node; if (encoding != null) this.defaultEncoding = encoding; } public boolean isProduceHTML() { return produceHTML; } public void setProduceHTML(boolean produceHTML) { this.produceHTML = produceHTML; } public boolean isPrettyPrint() { return prettyPrint; } public void setPrettyPrint(boolean prettyPrint) { this.prettyPrint = prettyPrint; } private void writeNode(Writer writer, Node node) throws IOException { short type = node.getNodeType(); switch (type) { case Node.DOCUMENT_NODE: document(writer, (Document) node); break; case Node.DOCUMENT_FRAGMENT_NODE: documentFragment(writer, (DocumentFragment) node); break; case Node.DOCUMENT_TYPE_NODE: documentType(writer, (DocumentType) node); break; case Node.ELEMENT_NODE: element(writer, (Element) node); break; case Node.ATTRIBUTE_NODE: attribute(writer, (Attr) node); break; case Node.ENTITY_REFERENCE_NODE: entityReference(writer, (EntityReference) node); break; case Node.ENTITY_NODE: entity(writer, (Entity) node); break; case Node.NOTATION_NODE: notation(writer, (Notation) node); break; case Node.PROCESSING_INSTRUCTION_NODE: procInst(writer, (ProcessingInstruction) node); break; case Node.TEXT_NODE: text(writer, (Text) node); break; case Node.CDATA_SECTION_NODE: cDataSection(writer, (CDATASection) node); break; case Node.COMMENT_NODE: comment(writer, (Comment) node); break; } } private String getChildText(Node node) { StringBuffer sb = new StringBuffer(); NodeList l = node.getChildNodes(); int size = l.getLength(); for (int i = 0; i < size; i++) { Node n = l.item(i); if (n.getNodeType() == Node.TEXT_NODE) { Text t = (Text) n; sb.append(t.getData()); } else return null; } return sb.toString(); } private void writeChildren(Writer writer, Node node) throws IOException { NodeList l = node.getChildNodes(); int size = l.getLength(); for (int i = 0; i < size; i++) { Node n = l.item(i); writeNode(writer, n); } } private void document(Writer writer, Document doc) throws IOException { if (!produceHTML) { writer.write("<?xml version=\"1.0\" encoding=\""); writer.write(defaultEncoding); writer.write("\"?>\n"); } writeChildren(writer, doc); } private void documentFragment(Writer writer, DocumentFragment fragment) throws IOException { writeChildren(writer, fragment); } private void documentType(Writer writer, DocumentType docType) throws IOException { writer.write("<!DOCTYPE "); writer.write(docType.getName()); String pubID = docType.getPublicId(); String sysID = docType.getSystemId(); if (pubID != null) { writer.write(" PUBLIC "); writer.write(pubID); if (sysID != null) { writer.write(' '); writer.write(sysID); } } else if (sysID != null) { writer.write(" SYSTEM "); writer.write(sysID); } String is = docType.getInternalSubset(); if (is != null) { writer.write(" ["); writer.write(is); writer.write("]"); } writer.write(">\n"); } private void element(Writer writer, Element elem) throws IOException { if (prettyPrint) { checkTextBuffer(writer); indent(writer); } String n = elem.getTagName(); writer.write('<'); writeText(writer, n); NamedNodeMap a = elem.getAttributes(); int size = a.getLength(); for (int i = 0; i < size; i++) { Attr att = (Attr) a.item(i); writer.write(' '); writeNode(writer, att); } if (elem.hasChildNodes()) { writer.write('>'); if (prettyPrint) { String text = getChildText(elem); if (text != null) writeEscapedText(writer, normalizeString(text), false); else { writer.write('\n'); indentLevel++; writeChildren(writer, elem); checkTextBuffer(writer); indentLevel--; indent(writer); } } else writeChildren(writer, elem); writer.write("</"); writeText(writer, n); writer.write('>'); } else { if (produceHTML) writer.write(">"); else writer.write("/>"); } if (prettyPrint) writer.write('\n'); } private void attribute(Writer writer, Attr attr) throws IOException { writeText(writer, attr.getName()); writer.write("=\""); //writeEscapedText(writer, attr.getValue(), true); writer.write(StringEscapeUtils.escapeXml(attr.getValue())); writer.write("\""); } private void entityReference(Writer writer, EntityReference entityRef) throws IOException { } private void entity(Writer writer, Entity entity) throws IOException { } private void notation(Writer writer, Notation notation) throws IOException { if (prettyPrint) { checkTextBuffer(writer); indent(writer); } writer.write("<!NOTATION "); writer.write(notation.getNodeName()); String pubID = notation.getPublicId(); String sysID = notation.getSystemId(); if (pubID != null) { writer.write(" PUBLIC "); writer.write(pubID); if (sysID != null) { writer.write(' '); writer.write(sysID); } } else if (sysID != null) { writer.write(" SYSTEM "); writer.write(sysID); } writer.write(">\n"); } private void procInst(Writer writer, ProcessingInstruction pi) throws IOException { if (prettyPrint) { checkTextBuffer(writer); indent(writer); } writer.write("<?"); writeText(writer, pi.getTarget()); writer.write(" "); writeText(writer, pi.getData()); writer.write("?>\n"); } private void text(Writer writer, Text text) throws IOException { if (prettyPrint) textBuffer.append(text.getData()); else writeEscapedText(writer, text.getData(), false); } private void cDataSection(Writer writer, CDATASection cdata) throws IOException { if (prettyPrint) { checkTextBuffer(writer); indent(writer); } writer.write("<![CDATA["); writer.write(cdata.getData()); writer.write("]]>"); if (prettyPrint) writer.write('\n'); } private void comment(Writer writer, Comment comment) throws IOException { if (prettyPrint) { checkTextBuffer(writer); indent(writer); } writer.write("<!--"); writeText(writer, comment.getData()); writer.write("-->"); if (prettyPrint) writer.write('\n'); } private void writeText(Writer writer, String text) throws IOException { if (text != null) writer.write(text); } private void writeEscapedText(Writer writer, String text, boolean attr) throws IOException { if (text != null) { char[] value = text.toCharArray(); String outval = null; int start = 0; int len = 0; for (int i = 0; i < value.length; i++) { char c = value[i]; switch (c) { case '\"': outval = """; break; case '<': outval = "<"; break; case '>': outval = ">"; break; case '&': if (produceHTML && attr) len++; else outval = "&"; break; case '\'': if (produceHTML) len++; else outval = "'"; break; case ' ': case '\n': case '\r': case '\t': len++; continue; default: // if ( c < ' ' || c == 127 ) { // outval = "&#x" + Integer.toHexString(c) + ";"; // break; // } // else { len++; continue; // } } if (outval != null) { if (len > 0) { String s = new String(value, start, len); writer.write(value, start, len); } writer.write(outval); start = i + 1; len = 0; outval = null; } } if (len > 0) writer.write(value, start, len); } } private void checkTextBuffer(Writer writer) throws IOException { if (textBuffer.length() > 0) { String val = normalizeString(textBuffer.toString()); textBuffer.setLength(0); if (val.length() > 0) { indent(writer); writeEscapedText(writer, val, false); writer.write('\n'); } } } private void indent(Writer writer) throws IOException { indent(writer, indentLevel); } private void indent(Writer writer, int level) throws IOException { int size = level * indentSize; if (size > 0) { if (indentTemplate.length() < size) { StringBuffer sb = new StringBuffer(indentTemplate); for (int i = indentTemplate.length(); i < size; i++) sb.append(' '); indentTemplate = sb.toString(); } writer.write(indentTemplate.substring(0, size)); } } private String normalizeString(String value) { char[] c = value.toCharArray(); char[] n = new char[c.length]; boolean white = true; int pos = 0; for (int i = 0; i < c.length; i++) { if (" \t\n\r".indexOf(c[i]) != -1) { if (!white) { n[pos++] = ' '; white = true; } } else { n[pos++] = c[i]; white = false; } } if (white && pos > 0) pos--; return new String(n, 0, pos); } /** * write writes the specified node to the writer as text. * * @param node The Node to write * @param writer The Writer to write to */ public static void write(Node node, Writer writer) throws IOException { new TextWriter(node).write(writer); } /** * writeHTML writes the specified node to the writer as HTML. * * @param node The Node to write * @param writer The Writer to write to */ public static void writeHTML(Node node, Writer writer) throws IOException { new TextWriter(node, true).write(writer); } /** * writePretty writes the specified node to the writer as pretty text. * * @param node The Node to write * @param writer The Writer to write to */ public static void writePretty(Node node, Writer writer) throws IOException { new TextWriter(node, false, true).write(writer); } /** * writePrettyHTML writes the specified node to the writer as pretty HTML. * * @param node The Node to write * @param writer The Writer to write to */ public static void writePrettyHTML(Node node, Writer writer) throws IOException { new TextWriter(node, true, true).write(writer); } /** * write writes the node to the writer as text. * * @param writer The Writer to write to */ public void write(Writer writer) throws IOException { try { BufferedWriter buf = new BufferedWriter(writer, 4096); writeNode(buf, node); buf.flush(); } catch (Exception e) { e.printStackTrace(System.err); } } /** * write writes the specified node to the OutputStream as text. * * @param node The Node to write * @param output The OutputStream to write to */ public static void write(Node node, OutputStream output) throws IOException { new TextWriter(node).write(output); } /** * writeHTML writes the specified node to the OutputStream as HTML. * * @param node The Node to write * @param output The OutputStream to write to */ public static void writeHTML(Node node, OutputStream output) throws IOException { new TextWriter(node, true).write(output); } /** * writePretty writes the specified node to the OutputStream as pretty text. * * @param node The Node to write * @param output The OutputStream to write to */ public static void writePretty(Node node, OutputStream output) throws IOException { new TextWriter(node, false, true).write(output); } /** * writePrettyHTML writes the specified node to the OutputStream as pretty HTML. * * @param node The Node to write * @param output The OutputStream to write to */ public static void writePrettyHTML(Node node, OutputStream output) throws IOException { new TextWriter(node, true, true).write(output); } /** * write writes the node to the OutputStream as text. * * @param output The OutputStream to write to */ public void write(OutputStream output) throws IOException { try { OutputStreamWriter o = new OutputStreamWriter(output, "UTF8"); BufferedWriter buf = new BufferedWriter(o, 4096); writeNode(buf, node); buf.flush(); } catch (Exception e) { e.printStackTrace(System.err); } } /** * toString returns the node as a String. * * @param node The Node to convert * @return The String value */ public static String toString(Node node) { return new TextWriter(node).toString(); } public static String toString(Node node, String encoding) { return new TextWriter(node, encoding).toString(); } /** * toHTMLString returns the node as a HTML String. * * @param node The Node to convert * @return The String value */ public static String toHTMLString(Node node) { return new TextWriter(node, true).toString(); } /** * toPrettyString returns the node as a Pretty String. * * @param node The Node to convert * @return The String value */ public static String toPrettyString(Node node) { return new TextWriter(node, false, true).toString(); } /** * toPrettyHTMLString returns the node as a Pretty HTML String. * * @param node The Node to convert * @return The String value */ public static String toPrettyHTMLString(Node node) { return new TextWriter(node, true, true).toString(); } /** * toString returns the node as a String. * * @return The String value */ @Override public String toString() { StringWriter writer = new StringWriter(); try { write(writer); return writer.toString(); } catch (Exception e) { e.printStackTrace(System.err); return null; } } }