/*
* Modified by Dimitry Polivaev (2010)
*
* XMLWriter.java NanoXML/Java $Revision: 1.4 $ $Date: 2002/03/24 11:37:51 $
* $Name: RELEASE_2_2_1 $ This file is part of NanoXML 2 for Java. Copyright (C)
* 2000-2002 Marc De Scheemaecker, All Rights Reserved. This software is
* provided 'as-is', without any express or implied warranty. In no event will
* the authors be held liable for any damages arising from the use of this
* software. Permission is granted to anyone to use this software for any
* purpose, including commercial applications, and to alter it and redistribute
* it freely, subject to the following restrictions: 1. The origin of this
* software must not be misrepresented; you must not claim that you wrote the
* original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required. 2.
* Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software. 3. This notice may not be
* removed or altered from any source distribution.
*/
package org.freeplane.core.io.xml;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Enumeration;
import java.util.Vector;
import org.freeplane.n3.nanoxml.XMLElement;
/**
* An XMLWriter writes XML data to a stream.
*
* @see org.freeplane.n3.nanoxml.XMLElement
* @see java.io.Writer
* @author Marc De Scheemaecker Modified by Dimitry Polivaev: optionally not
* write closing element tag
*/
class XMLWriter {
/**
* Where to write the output to.
*/
private PrintWriter writer;
public void flush() {
writer.flush();
}
/**
* Creates a new XML writer.
*
* @param stream
* where to write the output to.
*/
public XMLWriter(final OutputStream stream) {
writer = new PrintWriter(stream);
}
/**
* Creates a new XML writer.
*
* @param writer
* where to write the output to.
*/
public XMLWriter(final Writer writer) {
if (writer instanceof PrintWriter) {
this.writer = (PrintWriter) writer;
}
else {
this.writer = new PrintWriter(writer);
}
}
public void endElement(final String fullName, final boolean prettyPrint) {
writer.print("</" + fullName + '>');
if (prettyPrint) {
writer.println();
}
}
/**
* Cleans up the object when it's destroyed.
*/
@Override
protected void finalize() throws Throwable {
flush();
writer = null;
super.finalize();
}
/**
* Writes an XML element.
*
* @param xml
* the non-null XML element to write.
*/
public void startElement(final XMLElement xml) throws IOException {
this.write(xml, false, 0, true, false);
}
/**
*/
public void write(final String content) {
writeEncoded(content, false, true);
}
/**
* Writes an XML element.
*
* @param xml
* the non-null XML element to write.
*/
public void write(final XMLElement xml) throws IOException {
this.write(xml, false, 0, true, true);
}
/**
* Writes an XML element.
*
* @param xml
* the non-null XML element to write.
* @param prettyPrint
* if spaces need to be inserted to make the output more readable
* @param indent
* how many spaces to indent the element.
* @param endElement
*/
protected void write(final XMLElement xml, final boolean prettyPrint, final int indent,
final boolean collapseEmptyElements, final boolean endElement) throws IOException {
if (prettyPrint) {
for (int i = 0; i < indent; i++) {
writer.print(' ');
}
}
if (xml.getName() == null) {
if (xml.getContent() != null) {
if (prettyPrint) {
this.writeEncoded(xml.getContent().trim(), false, false);
writer.println();
}
else {
this.writeEncoded(xml.getContent(), false, false);
}
}
}
else {
writer.print('<');
final String fullName = xml.getFullName();
writer.print(fullName);
final Vector<String> nsprefixes = new Vector<String>();
if (xml.getNamespace() != null) {
if (xml.getName().equals(fullName)) {
writer.print(" xmlns=\"" + xml.getNamespace() + '"');
}
else {
String prefix = fullName;
prefix = prefix.substring(0, prefix.indexOf(':'));
nsprefixes.addElement(prefix);
writer.print(" xmlns:" + prefix);
writer.print("=\"" + xml.getNamespace() + "\"");
}
}
Enumeration<String> enumAttributeNames = xml.enumerateAttributeNames();
while (enumAttributeNames.hasMoreElements()) {
final String key = (String) enumAttributeNames.nextElement();
final int index = key.indexOf(':');
if (index >= 0) {
final String namespace = xml.getAttributeNamespace(key);
if (namespace != null) {
final String prefix = key.substring(0, index);
if (!nsprefixes.contains(prefix)) {
writer.print(" xmlns:" + prefix);
writer.print("=\"" + namespace + '"');
nsprefixes.addElement(prefix);
}
}
}
}
enumAttributeNames = xml.enumerateAttributeNames();
while (enumAttributeNames.hasMoreElements()) {
final String key = (String) enumAttributeNames.nextElement();
final String value = xml.getAttribute(key, null);
writer.print(" " + key + "=\"");
this.writeEncoded(value, true, false);
writer.print('"');
}
if ((xml.getContent() != null) && (xml.getContent().length() > 0)) {
writer.print('>');
this.writeEncoded(xml.getContent(), false, false);
if (endElement) {
endElement(fullName, prettyPrint);
}
}
else if (xml.hasChildren() || (!collapseEmptyElements)) {
writer.print('>');
if (prettyPrint) {
writer.println();
}
Enumeration<XMLElement> enumeration = xml.enumerateChildren();
while (enumeration.hasMoreElements()) {
final XMLElement child = enumeration.nextElement();
this.write(child, prettyPrint, indent + 4, collapseEmptyElements, true);
}
if (prettyPrint) {
for (int i = 0; i < indent; i++) {
writer.print(' ');
}
}
if (endElement) {
endElement(fullName, prettyPrint);
}
}
else {
if (endElement) {
writer.print("/>");
}
else {
writer.print(">");
}
if (prettyPrint) {
writer.println();
}
}
}
}
/**
* Writes a string encoding reserved characters.
*/
private void writeEncoded(final String str, final boolean atributeValue, final boolean xmlInclude) {
for (int i = 0; i < str.length(); i++) {
final char c = str.charAt(i);
if (c > 0x7E) {
writer.print("");
writer.print(Integer.toString(c, 16));
writer.print(';');
continue;
}
if (xmlInclude) {
writer.print(c);
continue;
}
switch (c) {
case '<':
writer.print("<");
continue;
case '>':
writer.print(">");
continue;
case '&':
writer.print("&");
continue;
case '\'':
writer.print("'");
continue;
case '"':
writer.print(""");
continue;
case 0x0A:
if (atributeValue) {
writer.print("
");
}
else {
writer.print(c);
}
continue;
default:
if (c < ' ') {
writer.print("");
writer.print(Integer.toString(c, 16));
writer.print(';');
continue;
}
writer.print(c);
}
}
}
}