001/*
002 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
003 * 
004 * This software is open source. 
005 * See the bottom of this file for the licence.
006 * 
007 * $Id: OutputFormat.java,v 1.7 2001/11/14 18:02:32 jstrachan Exp $
008 */
009
010package org.dom4j.io;
011
012/** <p><code>OutputFormat</code> represents the format configuration
013  * used by {@link XMLWriter} and its base classes to format the XML output
014  *
015  * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a>
016  * @version $Revision: 1.7 $
017  */
018public class OutputFormat implements Cloneable {
019
020    /** standard value to indent by, if we are indenting **/
021    protected static final String STANDARD_INDENT = "  ";
022    
023    /** Whether or not to suppress the XML declaration - default is <code>false</code> */
024    private boolean suppressDeclaration = false;
025
026    /** The encoding format */
027    private String encoding = "UTF-8";
028
029    /** Whether or not to output the encoding in the XML declaration - default is <code>false</code> */
030    private boolean omitEncoding = false;
031
032    /** The default indent is no spaces (as original document) */
033    private String indent = null;
034
035    /** Whether or not to expand empty elements to &lt;tagName&gt;&lt;/tagName&gt; - default is <code>false</code> */
036    private boolean expandEmptyElements = false;
037
038    /** The default new line flag, set to do new lines only as in original document */
039    private boolean newlines = false;
040
041    /** New line separator */
042    private String lineSeparator = "\n";
043
044    /** should we preserve whitespace or not in text nodes? */
045    private boolean trimText = false;
046
047    /** pad string-element boundaries with whitespace **/
048    private boolean padText = false;
049
050    /** Creates an <code>OutputFormat</code> with
051      * no additional whitespace (indent or new lines) added.
052      * The whitespace from the element text content is fully preserved.
053      */
054    public OutputFormat() {
055    }
056
057    /** Creates an <code>OutputFormat</code> with the given indent added but
058      * no new lines added. All whitespace from element text will be included.
059      * 
060      * @param indent is the indent string to be used for indentation 
061      * (usually a number of spaces).
062      */
063    public OutputFormat(String indent) {
064        this.indent = indent;
065    }
066
067    /** Creates an <code>OutputFormat</code> with the given indent added 
068      * with optional newlines between the Elements. 
069      * All whitespace from element text will be included.
070      * 
071      * @param indent is the indent string to be used for indentation 
072      *     (usually a number of spaces).
073      * @param newlines whether new lines are added to layout the
074      */
075    public OutputFormat(String indent, boolean newlines) {
076        this.indent = indent;
077        this.newlines = newlines;
078    }
079
080    /** Creates an <code>OutputFormat</code> with the given indent added 
081      * with optional newlines between the Elements
082      * and the given encoding format.
083      * 
084      * @param indent is the indent string to be used for indentation 
085      *     (usually a number of spaces).
086      * @param newlines whether new lines are added to layout the
087      * @param encoding is the text encoding to use for writing the XML
088      */
089    public OutputFormat(String indent, boolean newlines, String encoding) {
090        this.indent = indent;
091        this.newlines = newlines;
092        this.encoding = encoding;
093    }
094
095    public String getLineSeparator() {
096        return lineSeparator;
097    }
098
099    
100    /** <p>This will set the new-line separator. The default is
101      * <code>\n</code>. Note that if the "newlines" property is
102      * false, this value is irrelevant.  To make it output the system
103      * default line ending string, call
104      * <code>setLineSeparator(System.getProperty("line.separator"))</code>
105      * </p>
106      * @see #setNewlines(boolean)
107      * @param separator <code>String</code> line separator to use.
108      */
109    public void setLineSeparator(String separator) {
110        lineSeparator = separator;
111    }
112
113    public boolean isNewlines() {
114        return newlines;
115    }
116
117    /** @see #setLineSeparator(String)
118      * @param newlines <code>true</code> indicates new lines should be
119      *                 printed, else new lines are ignored (compacted).
120      */
121    public void setNewlines(boolean newlines) {
122        this.newlines = newlines;
123    }
124
125    public String getEncoding() {
126        return encoding;
127    }
128
129    /** @param encoding encoding format */
130    public void setEncoding(String encoding) {
131        this.encoding = encoding;
132    }
133
134    public boolean isOmitEncoding() {
135        return omitEncoding;
136    }
137
138    /** <p> This will set whether the XML declaration 
139      * (<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code>)
140      * includes the encoding of the document. 
141      * It is common to suppress this in protocols such as WML and SOAP.</p>
142      *
143      * @param omitEncoding <code>boolean</code> indicating whether or not
144      *        the XML declaration should indicate the document encoding.
145      */
146    public void setOmitEncoding(boolean omitEncoding) {
147        this.omitEncoding = omitEncoding;
148    }
149
150    /** <p> This will set whether the XML declaration 
151      * (<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code>)
152      * is included or not.
153      * It is common to suppress this in protocols such as WML and SOAP.</p>
154      *
155      * @param suppressDeclaration <code>boolean</code> indicating whether or not
156      *     the XML declaration should be suppressed.
157      */
158    public void setSuppressDeclaration(boolean suppressDeclaration) {
159        this.suppressDeclaration = suppressDeclaration;
160    }
161
162    /** @return true if the output of the XML declaration
163      * (<code>&lt;?xml version="1.0"?&gt;</code>) should be suppressed else false.
164      */
165    public boolean isSuppressDeclaration() {
166        return suppressDeclaration;
167    }
168    
169    public boolean isExpandEmptyElements() {
170        return expandEmptyElements;
171    }
172    
173    /** <p>This will set whether empty elements are expanded from 
174      * <code>&lt;tagName&gt;</code> to
175      * <code>&lt;tagName&gt;&lt;/tagName&gt;</code>.</p>
176      *
177      * @param expandEmptyElements <code>boolean</code> indicating whether or not
178      *     empty elements should be expanded.
179      */
180    public void setExpandEmptyElements(boolean expandEmptyElements) {
181        this.expandEmptyElements = expandEmptyElements;
182    }
183
184    public boolean isTrimText() {
185        return trimText;
186    }
187
188    /** <p> This will set whether the text is output verbatim (false)
189      *  or with whitespace stripped as per <code>{@link
190      *  org.dom4j.Element#getTextTrim()}</code>.<p>
191      *
192      * <p>Default: false </p>
193      *
194      * @param trimText <code>boolean</code> true=>trim the whitespace, false=>use text verbatim
195      */
196    public void setTrimText(boolean trimText) {
197        this.trimText = trimText;
198    }
199
200    public boolean isPadText() {
201        return padText;
202    }
203    
204    /** <p> Ensure that text immediately preceded by or followed by an
205      * element will be "padded" with a single space.  This is used to
206      * allow make browser-friendly HTML, avoiding trimText's
207      * transformation of, e.g., 
208      * <code>The quick &lt;b&gt;brown&lt;/b&gt; fox</code> into
209      * <code>The quick&lt;b&gt;brown&lt;/b&gt;fox</code> (the latter
210      * will run the three separate words together into a single word).
211      *
212      * This setting is not too useful if you haven't also called
213      * {@link #setTrimText}.</p>
214      * 
215      * <p>Default: false </p>
216      *
217      * @param padText <code>boolean</code> if true, pad string-element boundaries
218      */
219    public void setPadText(boolean padText) {
220        this.padText = padText;
221    }
222
223    public String getIndent() {
224        return indent;
225    }
226    
227    /** <p> This will set the indent <code>String</code> to use; this
228      * is usually a <code>String</code> of empty spaces. If you pass
229      * null, or the empty string (""), then no indentation will
230      * happen. </p>
231      * Default: none (null)
232      *
233      * @param indent <code>String</code> to use for indentation.
234      */
235    public void setIndent(String indent) {
236        // nullify empty string to void unnecessary indentation code
237        if ( indent != null && indent.length() <= 0 ) {
238            indent = null;
239        }
240        this.indent = indent;
241    }
242
243    /** Set the indent on or off.  If setting on, will use the value of
244      * STANDARD_INDENT, which is usually two spaces.
245      *
246      * @param doIndent if true, set indenting on; if false, set indenting off
247      */
248    public void setIndent(boolean doIndent) {
249        if (doIndent) { 
250            this.indent = STANDARD_INDENT;
251        }
252        else {
253            this.indent = null;
254        }
255    }
256
257    /** <p>This will set the indent <code>String</code>'s size; an indentSize
258      * of 4 would result in the indention being equivalent to the <code>String</code>
259      * "&nbsp;&nbsp;&nbsp;&nbsp;" (four space characters).</p>
260      *
261      * @param indentSize <code>int</code> number of spaces in indentation.
262      */
263    public void setIndentSize(int indentSize) {
264        StringBuffer indentBuffer = new StringBuffer();
265        for ( int i = 0; i < indentSize; i++ ) {
266            indentBuffer.append(" ");
267        }
268        this.indent = indentBuffer.toString();
269    }
270    
271    /** Parses command line arguments of the form 
272      * <code>-omitEncoding -indentSize 3 -newlines -trimText</code>
273      *
274      * @param args is the array of command line arguments
275      * @param i is the index in args to start parsing options
276      * @return the index of first parameter that we didn't understand
277      */      
278    public int parseOptions(String[] args, int i) {
279        for ( int size = args.length; i < size; i++ ) {
280            if (args[i].equals("-suppressDeclaration")) {
281                setSuppressDeclaration(true);
282            }
283            else if (args[i].equals("-omitEncoding")) {
284                setOmitEncoding(true);
285            }
286            else if (args[i].equals("-indent")) {
287                setIndent(args[++i]);
288            }
289            else if (args[i].equals("-indentSize")) {
290                setIndentSize(Integer.parseInt(args[++i]));
291            }
292            else if (args[i].startsWith("-expandEmpty")) {
293                setExpandEmptyElements(true);
294            }
295            else if (args[i].equals("-encoding")) {
296                setEncoding(args[++i]);
297            }
298            else if (args[i].equals("-newlines")) {
299                setNewlines(true);
300            }
301            else if (args[i].equals("-lineSeparator")) {
302                setLineSeparator(args[++i]);
303            }
304            else if (args[i].equals("-trimText")) {
305                setTrimText(true);
306            }
307            else if (args[i].equals("-padText")) {
308                setPadText(true);
309            }
310            else {
311                return i;
312            }
313        }
314        return i;
315    } 
316    
317
318    /** A static helper method to create the default pretty printing format.
319      * This format consists of an indent of 2 spaces, newlines after each
320      * element and all other whitespace trimmed 
321      */    
322    public static OutputFormat createPrettyPrint() {
323        OutputFormat format = new OutputFormat();
324        format.setIndentSize( 2 );
325        format.setNewlines(true);
326        format.setTrimText(true);
327        return format;
328    }
329
330    /** A static helper method to create the default compact format.
331      * This format does not have any indentation or newlines after an alement 
332      * and all other whitespace trimmed 
333      */    
334    public static OutputFormat createCompactFormat() {
335        OutputFormat format = new OutputFormat();
336        format.setIndent(false);
337        format.setNewlines(false);
338        format.setTrimText(true);
339        return format;
340    }
341    
342}
343
344
345
346
347/*
348 * Redistribution and use of this software and associated documentation
349 * ("Software"), with or without modification, are permitted provided
350 * that the following conditions are met:
351 *
352 * 1. Redistributions of source code must retain copyright
353 *    statements and notices.  Redistributions must also contain a
354 *    copy of this document.
355 *
356 * 2. Redistributions in binary form must reproduce the
357 *    above copyright notice, this list of conditions and the
358 *    following disclaimer in the documentation and/or other
359 *    materials provided with the distribution.
360 *
361 * 3. The name "DOM4J" must not be used to endorse or promote
362 *    products derived from this Software without prior written
363 *    permission of MetaStuff, Ltd.  For written permission,
364 *    please contact dom4j-info@metastuff.com.
365 *
366 * 4. Products derived from this Software may not be called "DOM4J"
367 *    nor may "DOM4J" appear in their names without prior written
368 *    permission of MetaStuff, Ltd. DOM4J is a registered
369 *    trademark of MetaStuff, Ltd.
370 *
371 * 5. Due credit should be given to the DOM4J Project
372 *    (http://dom4j.org/).
373 *
374 * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
375 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
376 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
377 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
378 * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
379 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
380 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
381 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
382 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
383 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
384 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
385 * OF THE POSSIBILITY OF SUCH DAMAGE.
386 *
387 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
388 *
389 * $Id: OutputFormat.java,v 1.7 2001/11/14 18:02:32 jstrachan Exp $
390 */