/* eXist Native XML Database * Copyright (C) 2000-03, Wolfgang M. Meier (wolfgang@exist-db.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library 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 Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Id$ */ package org.exist.util.serializer; import java.io.Writer; import java.util.Properties; import javax.xml.transform.OutputKeys; import javax.xml.transform.TransformerException; import org.exist.dom.QName; import org.exist.storage.serializers.EXistOutputKeys; public class IndentingXMLWriter extends XMLWriter { private boolean indent = false; private int indentAmount = 4; private String indentChars = " "; private int level = 0; private boolean afterTag = false; private boolean sameline = false; public IndentingXMLWriter() { super(); } /** * @param writer */ public IndentingXMLWriter(Writer writer) { super(writer); } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#setWriter(java.io.Writer) */ public void setWriter(Writer writer) { super.setWriter(writer); level = 0; afterTag = false; sameline = false; } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#startElement(java.lang.String) */ public void startElement(String qname) throws TransformerException { if(afterTag) indent(); super.startElement(qname); level++; afterTag = true; sameline = true; } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#startElement(org.exist.dom.QName) */ public void startElement(QName qname) throws TransformerException { if(afterTag) indent(); super.startElement(qname); level++; afterTag = true; sameline = true; } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#endElement() */ public void endElement(String qname) throws TransformerException { level--; if (afterTag && !sameline) indent(); super.endElement(qname); sameline = false; afterTag = true; } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#endElement(org.exist.dom.QName) */ public void endElement(QName qname) throws TransformerException { level--; if (afterTag && !sameline) indent(); super.endElement(qname); sameline = false; afterTag = true; } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#characters(java.lang.CharSequence) */ public void characters(CharSequence chars) throws TransformerException { int start = 0, length = chars.length(); // while (length > 0 && isWhiteSpace(chars.charAt(start))) { // --length; // if(length > 0) // ++start; // } // while (length > 0 && isWhiteSpace(chars.charAt(start + length - 1))) { // --length; // } if(length == 0) return; // whitespace only: skip if(start > 0 || length < chars.length()) { chars = chars.subSequence(start, length); // drop whitespace } for(int i = 0; i < chars.length(); i++) { if(chars.charAt(i) == '\n') { sameline = false; } } afterTag = false; super.characters(chars); } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#comment(java.lang.String) */ public void comment(CharSequence data) throws TransformerException { super.comment(data); afterTag = true; } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#processingInstruction(java.lang.String, java.lang.String) */ public void processingInstruction(String target, String data) throws TransformerException { super.processingInstruction(target, data); afterTag = true; } public void documentType(String name, String publicId, String systemId) throws TransformerException { super.documentType(name, publicId, systemId); super.characters("\n"); sameline = false; } /* (non-Javadoc) * @see org.exist.util.serializer.XMLWriter#setOutputProperties(java.util.Properties) */ public void setOutputProperties(Properties properties) { super.setOutputProperties(properties); String option = outputProperties.getProperty(EXistOutputKeys.INDENT_SPACES, "4"); try { indentAmount = Integer.parseInt(option); } catch(NumberFormatException e) { } indent = outputProperties.getProperty(OutputKeys.INDENT, "no").equals("yes"); } protected void indent() throws TransformerException { if(!indent) return; int spaces = indentAmount * level; while(spaces >= indentChars.length()) indentChars += indentChars; super.characters("\n"); super.characters(indentChars.subSequence(0, spaces)); sameline = false; } protected final static boolean isWhiteSpace(char ch) { return (ch == 0x20) || (ch == 0x09) || (ch == 0xD) || (ch == 0xA); } }