001package com.hfg.xml.parser; 002 003import java.io.*; 004import java.util.ArrayList; 005import java.util.Collection; 006 007import org.xml.sax.Attributes; 008import org.xml.sax.SAXException; 009 010import com.hfg.util.StringUtil; 011import com.hfg.xml.XMLAttribute; 012import com.hfg.xml.XMLUtil; 013 014//------------------------------------------------------------------------------ 015/** 016 * XML SAX ContentHandler that reproduces the XML. Useful in conjunction with 017 * pseudo-SAX parsers that operate on non-XML files (the NcbiASN1BinarySAXParser 018 * for example.) 019 * 020 * @author J. Alex Taylor, hairyfatguy.com 021 */ 022//------------------------------------------------------------------------------ 023// com.hfg XML/HTML Coding Library 024// 025// This library is free software; you can redistribute it and/or 026// modify it under the terms of the GNU Lesser General Public 027// License as published by the Free Software Foundation; either 028// version 2.1 of the License, or (at your option) any later version. 029// 030// This library is distributed in the hope that it will be useful, 031// but WITHOUT ANY WARRANTY; without even the implied warranty of 032// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 033// Lesser General Public License for more details. 034// 035// You should have received a copy of the GNU Lesser General Public 036// License along with this library; if not, write to the Free Software 037// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 038// 039// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 040// jataylor@hairyfatguy.com 041//------------------------------------------------------------------------------ 042 043public class XMLRepeatContentHandler extends AbstractContentHandler 044{ 045 private BufferedWriter mWriter; 046 private String mIndent = " "; 047 private int mIndentCount; 048 private METHOD mLastMethod; 049 050 private String mCurrentStartTag; 051 private Collection<XMLAttribute> mCurrentAttributes; 052 053 054 private static enum METHOD { startElement, endElement, characters } 055 056 //----------------------------------------------------------------------- 057 public XMLRepeatContentHandler(OutputStream stream) 058 { 059 mWriter = new BufferedWriter(new OutputStreamWriter(stream)); 060 } 061 062 063 //----------------------------------------------------------------------- 064 public XMLRepeatContentHandler setIndentSize(int inValue) 065 { 066 mIndent = StringUtil.polyChar(' ', inValue); 067 return this; 068 } 069 070 //----------------------------------------------------------------------- 071 @Override 072 public void startDocument() 073 throws SAXException 074 { 075 try 076 { 077 mWriter.write("<?xml version='1.0' ?>"); 078 mWriter.newLine(); 079 } 080 catch (IOException e) 081 { 082 throw new SAXException(e); 083 } 084 } 085 086 //----------------------------------------------------------------------- 087 @Override 088 public void endDocument() 089 throws SAXException 090 { 091 try 092 { 093 mWriter.close(); 094 } 095 catch (IOException e) 096 { 097 throw new SAXException(e); 098 } 099 } 100 101 //----------------------------------------------------------------------- 102 @Override 103 public void startElement(String inURI, String inLocalName, String inName, Attributes inAttributes) 104 { 105 try 106 { 107 if (mLastMethod == METHOD.startElement) 108 { 109 mWriter.write(XMLUtil.composeStartTag(mCurrentStartTag, mCurrentAttributes)); 110 111 mWriter.newLine(); 112 mIndentCount++; 113 } 114 115 mWriter.write(StringUtil.polyString(mIndent, mIndentCount)); 116 117 mCurrentStartTag = inName; 118 119 mCurrentAttributes = null; 120 if (inAttributes.getLength() > 0) 121 { 122 mCurrentAttributes = new ArrayList<XMLAttribute>(inAttributes.getLength()); 123 for (int i = 0; i < inAttributes.getLength(); i++) 124 { 125 mCurrentAttributes.add(new XMLAttribute(inAttributes.getQName(i), inAttributes.getValue(i))); 126 } 127 } 128 129// mWriter.write(XMLUtil.composeStartTag(inName, inAttributes)); 130 } 131 catch (IOException e) 132 { 133 throw new RuntimeException(e); 134 } 135 136 mLastMethod = METHOD.startElement; 137 } 138 139 //----------------------------------------------------------------------- 140 @Override 141 public void endElement(String inURI, String inLocalName, String inName) 142 { 143 try 144 { 145 if (mLastMethod == METHOD.endElement) 146 { 147 mWriter.write(StringUtil.polyString(mIndent, (mIndentCount--) - 1)); 148 } 149 150 if (mLastMethod == METHOD.startElement) 151 { 152 mWriter.write(XMLUtil.composeStartTag(mCurrentStartTag, mCurrentAttributes, XMLUtil.EMPTY_TAG)); 153 } 154 else 155 { 156 mWriter.write(XMLUtil.composeEndTag(inName)); 157 } 158 159 mWriter.newLine(); 160 } 161 catch (IOException e) 162 { 163 throw new RuntimeException(e); 164 } 165 166 mLastMethod = METHOD.endElement; 167 } 168 169 //----------------------------------------------------------------------- 170 @Override 171 public void characters(char[] inChars, int offset, int length) 172 { 173 try 174 { 175 mWriter.write(XMLUtil.composeStartTag(mCurrentStartTag, mCurrentAttributes, XMLUtil.NOT_EMPTY_TAG)); 176 mWriter.write(XMLUtil.escapeContentIfNecessary(new String(inChars, offset, length))); 177 } 178 catch (IOException e) 179 { 180 throw new RuntimeException(e); 181 } 182 183 mLastMethod = METHOD.characters; 184 } 185 186}