001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/framework/xml/DOMPrinter.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.framework.xml; 037 038 import java.io.PrintWriter; 039 040 import org.deegree.framework.util.StringTools; 041 import org.w3c.dom.Document; 042 import org.w3c.dom.NamedNodeMap; 043 import org.w3c.dom.Node; 044 import org.w3c.dom.NodeList; 045 046 /** 047 * <code>DOMPrinter</code> contains various methods to print DOM-XML-elements to a String,PrintWriter or Standard out. 048 * 049 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 050 * @author last edited by: $Author: mschneider $ 051 * 052 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 053 */ 054 public class DOMPrinter { 055 056 /** 057 * 058 * @param out 059 * @param node 060 */ 061 public static void printNode( PrintWriter out, Node node ) { 062 switch ( node.getNodeType() ) { 063 case Node.DOCUMENT_NODE: { 064 out.print( "<?xml version=\"1.0\"?>" ); 065 Document doc = (Document) node; 066 printNode( out, doc.getDocumentElement() ); 067 break; 068 } 069 case Node.ELEMENT_NODE: { 070 String name = node.getNodeName(); 071 out.print( "<" + name ); 072 NamedNodeMap attributes = node.getAttributes(); 073 for ( int i = 0; i < attributes.getLength(); i++ ) { 074 Node current = attributes.item( i ); 075 String value = current.getNodeValue(); 076 value = StringTools.replace( value, "&", "&", true ); 077 out.print( " " + current.getNodeName() + "=\"" + value + "\"" ); 078 } 079 out.print( ">" ); 080 081 // Kinder durchgehen 082 NodeList children = node.getChildNodes(); 083 if ( children != null ) { 084 for ( int i = 0; i < children.getLength(); i++ ) { 085 printNode( out, children.item( i ) ); 086 } 087 } 088 089 out.print( "</" + name + ">" ); 090 break; 091 } 092 case Node.TEXT_NODE: 093 case Node.CDATA_SECTION_NODE: { 094 String trimmed = node.getNodeValue().trim(); 095 if ( !trimmed.equals( "" ) ) 096 out.print( validateCDATA( trimmed ) ); 097 break; 098 } 099 case Node.PROCESSING_INSTRUCTION_NODE: { 100 break; 101 } 102 case Node.ENTITY_REFERENCE_NODE: { 103 break; 104 } 105 case Node.DOCUMENT_TYPE_NODE: { 106 break; 107 } 108 } 109 } 110 111 /** 112 * 113 * @param node 114 * @param indent 115 */ 116 public static void printNode( Node node, String indent ) { 117 if ( node == null ) { 118 return; 119 } 120 121 switch ( node.getNodeType() ) { 122 case Node.DOCUMENT_NODE: { 123 System.out.println( "<?xml version=\"1.0\"?>" ); 124 Document doc = (Document) node; 125 printNode( doc.getDocumentElement(), "" ); 126 break; 127 } 128 case Node.ELEMENT_NODE: { 129 String name = node.getNodeName(); 130 System.out.print( indent + "<" + name ); 131 NamedNodeMap attributes = node.getAttributes(); 132 for ( int i = 0; i < attributes.getLength(); i++ ) { 133 Node current = attributes.item( i ); 134 String value = current.getNodeValue(); 135 if ( value != null ) { 136 value = StringTools.replace( value, "&", "&", true ); 137 System.out.print( " " + current.getNodeName() + "=\"" + value + "\"" ); 138 } 139 } 140 // erwachsenen durchgehen 141 NodeList children = node.getChildNodes(); 142 if ( children != null && children.getLength() != 0 ) { 143 boolean complexContent = false; 144 for ( int i = 0; i < children.getLength(); i++ ) { 145 if ( children.item( i ).getNodeType() != Node.TEXT_NODE 146 && children.item( i ).getNodeType() != Node.CDATA_SECTION_NODE ) { 147 complexContent = true; 148 } 149 } 150 if ( complexContent ) { 151 System.out.println( ">" ); 152 } else { 153 System.out.print( ">" ); 154 } 155 156 for ( int i = 0; i < children.getLength(); i++ ) { 157 printNode( children.item( i ), indent + " " ); 158 } 159 160 if ( complexContent ) { 161 System.out.println( indent + "</" + name + ">" ); 162 } else { 163 System.out.println( "</" + name + ">" ); 164 } 165 } else { 166 System.out.println( "/>" ); 167 } 168 break; 169 } 170 case Node.TEXT_NODE: 171 case Node.CDATA_SECTION_NODE: { 172 if ( node.getNodeValue() != null ) { 173 String trimmed = node.getNodeValue().trim(); 174 if ( !trimmed.equals( "" ) ) 175 System.out.print( trimmed ); 176 } 177 break; 178 } 179 case Node.PROCESSING_INSTRUCTION_NODE: { 180 break; 181 } 182 case Node.ENTITY_REFERENCE_NODE: { 183 break; 184 } 185 case Node.DOCUMENT_TYPE_NODE: { 186 break; 187 } 188 } 189 } 190 191 /** 192 * 193 * @param node 194 * @param encoding 195 * @return the String representation of the given node. 196 */ 197 public static String nodeToString( Node node, String encoding ) { 198 StringBuilder sb = new StringBuilder( 10000 ); 199 200 switch ( node.getNodeType() ) { 201 case Node.DOCUMENT_NODE: { 202 sb.append( "<?xml version=\"1.0\" encoding=\"" + encoding + "\" ?>" ); 203 Document doc = (Document) node; 204 sb.append( nodeToString( doc.getDocumentElement(), "" ) ); 205 break; 206 } 207 case Node.ELEMENT_NODE: { 208 String name = node.getNodeName(); 209 sb.append( "\n<" + name ); 210 NamedNodeMap attributes = node.getAttributes(); 211 for ( int i = 0; i < attributes.getLength(); i++ ) { 212 Node current = attributes.item( i ); 213 String value = current.getNodeValue(); 214 if ( value != null ) { 215 value = StringTools.replace( value, "&", "&", true ); 216 sb.append( " " + current.getNodeName() + "=\"" + value + "\"" ); 217 } 218 } 219 sb.append( ">" ); 220 221 // Opas durchgehen 222 NodeList children = node.getChildNodes(); 223 if ( children != null ) { 224 for ( int i = 0; i < children.getLength(); i++ ) { 225 sb.append( nodeToString( children.item( i ), encoding ) ); 226 } 227 } 228 229 sb.append( "</" + name + ">" ); 230 break; 231 } 232 case Node.CDATA_SECTION_NODE: { 233 String trimmed = node.getNodeValue().trim(); 234 if ( !trimmed.equals( "" ) ) 235 sb.append( "<![CDATA[" + trimmed + "]]>" ); 236 break; 237 } 238 case Node.TEXT_NODE: { 239 String trimmed = node.getNodeValue(); 240 if ( trimmed != null ) { 241 trimmed = trimmed.trim(); 242 if ( !trimmed.equals( "" ) ) { 243 sb.append( validateCDATA( trimmed ) ); 244 } 245 } 246 break; 247 } 248 case Node.PROCESSING_INSTRUCTION_NODE: { 249 break; 250 } 251 case Node.ENTITY_REFERENCE_NODE: { 252 break; 253 } 254 case Node.DOCUMENT_TYPE_NODE: { 255 break; 256 } 257 } 258 return sb.toString(); 259 } 260 261 /** 262 * Checks if a given CDATA-value has to be escaped if it is used as a text value in an XML element. If the submitted 263 * string contains a character that have to be escaped or if the string is made of more than 1500 characters it is 264 * encapsulated into a CDATA-section. Returns a version that is safe to be used. 265 * <p> 266 * The method is just proofed for the UTF-8 character encoding. 267 * 268 * @param cdata 269 * value to be used 270 * @return the very same value (but escaped if necessary) 271 * @todo refactoring required 272 */ 273 public static StringBuffer validateCDATA( String cdata ) { 274 StringBuffer sb = null; 275 if ( cdata != null 276 && ( cdata.length() > 1000 || cdata.indexOf( '<' ) >= 0 || cdata.indexOf( '>' ) >= 0 277 || cdata.indexOf( '&' ) >= 0 || cdata.indexOf( '"' ) >= 0 || cdata.indexOf( "'" ) >= 0 ) ) { 278 sb = new StringBuffer( cdata.length() + 15 ); 279 sb.append( "<![CDATA[" ).append( cdata ).append( "]]>" ); 280 } else { 281 if ( cdata != null ) { 282 sb = new StringBuffer( cdata ); 283 } 284 } 285 return sb; 286 } 287 }