KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > event > XMLIndenter


1 package net.sf.saxon.event;
2 import net.sf.saxon.trans.XPathException;
3 import net.sf.saxon.style.StandardNames;
4
5 import javax.xml.transform.OutputKeys JavaDoc;
6 import java.util.Properties JavaDoc;
7
8 /**
9 * XMLIndenter: This ProxyReceiver indents elements, by adding character data where appropriate.
10 * The character data is always added as "ignorable white space", that is, it is never added
11 * adjacent to existing character data.
12 *
13 * @author Michael Kay
14 */

15
16
17 public class XMLIndenter extends ProxyReceiver {
18
19     private int level = 0;
20     private int indentSpaces = 3;
21     private String JavaDoc indentChars = "\n ";
22     private boolean sameline = false;
23     private boolean afterStartTag = false;
24     private boolean afterEndTag = true;
25     private boolean allWhite = true;
26     private int line = 0; // line and column measure the number of lines and columns
27
private int column = 0; // .. in whitespace text nodes between tags
28
private int suppressedAtLevel = -1;
29     private int xmlspace;
30
31     /**
32     * Set the properties for this indenter
33     */

34
35     public void setOutputProperties(Properties JavaDoc props) {
36         String JavaDoc s = props.getProperty(SaxonOutputKeys.INDENT_SPACES);
37         if (s==null) {
38             indentSpaces = 3;
39         } else {
40             try {
41                 indentSpaces = Integer.parseInt(s.trim());
42             } catch (NumberFormatException JavaDoc err) {
43                 indentSpaces = 3;
44             }
45         }
46         String JavaDoc omit = props.getProperty(OutputKeys.OMIT_XML_DECLARATION);
47         afterEndTag = omit==null || !omit.trim().equals("yes") ||
48                     props.getProperty(OutputKeys.DOCTYPE_SYSTEM)!=null ;
49     }
50
51     /**
52     * Start of document
53     */

54
55     public void open() throws XPathException {
56         super.open();
57         //xmlspace = getNamePool().allocate("xml", NamespaceConstant.XML, "space") & 0xfffff;
58
xmlspace = StandardNames.XML_SPACE;
59     }
60
61     /**
62     * Output element start tag
63     */

64
65     public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException {
66         if (afterStartTag || afterEndTag) {
67             indent();
68         }
69         super.startElement(nameCode, typeCode, locationId, properties);
70         level++;
71         sameline = true;
72         afterStartTag = true;
73         afterEndTag = false;
74         allWhite = true;
75         line = 0;
76     }
77
78     /**
79     * Output an attribute
80     */

81
82     public void attribute(int nameCode, int typeCode, CharSequence JavaDoc value, int locationId, int properties)
83     throws XPathException {
84         if ((nameCode & 0xfffff) == xmlspace && value.equals("preserve") && suppressedAtLevel < 0) {
85             suppressedAtLevel = level;
86         }
87         super.attribute(nameCode, typeCode, value, locationId, properties);
88     }
89
90     /**
91     * Output element end tag
92     */

93
94     public void endElement() throws XPathException {
95         level--;
96         if (afterEndTag && !sameline) {
97             indent();
98         }
99         super.endElement();
100         sameline = false;
101         afterEndTag = true;
102         afterStartTag = false;
103         allWhite = true;
104         line = 0;
105         if (level == (suppressedAtLevel - 1)) {
106             suppressedAtLevel = -1;
107             // remove the suppression of indentation
108
}
109     }
110
111     /**
112     * Output a processing instruction
113     */

114
115     public void processingInstruction(String JavaDoc target, CharSequence JavaDoc data, int locationId, int properties) throws XPathException {
116         if (afterEndTag) {
117             indent();
118         }
119         super.processingInstruction(target, data, locationId, properties);
120         afterStartTag = false;
121         afterEndTag = false;
122     }
123
124     /**
125     * Output character data
126     */

127
128     public void characters(CharSequence JavaDoc chars, int locationId, int properties) throws XPathException {
129         for (int i=0; i<chars.length(); i++) {
130             char c = chars.charAt(i);
131             if (c=='\n') {
132                 sameline = false;
133                 line++;
134                 column = 0;
135             }
136             if (!Character.isWhitespace(c)) {
137                 allWhite = false;
138             }
139             column++;
140         }
141         super.characters(chars, locationId, properties);
142         if (!allWhite) {
143             afterStartTag = false;
144             afterEndTag = false;
145         }
146     }
147
148     /**
149     * Output a comment
150     */

151
152     public void comment(CharSequence JavaDoc chars, int locationId, int properties) throws XPathException {
153         if (afterEndTag) {
154             indent();
155         }
156         super.comment(chars, locationId, properties);
157         afterStartTag = false;
158         afterEndTag = false;
159     }
160
161     /**
162     * Output white space to reflect the current indentation level
163     */

164
165     private void indent() throws XPathException {
166         if (suppressedAtLevel >= 0) {
167             // indentation has been suppressed (e.g. by xmlspace="preserve")
168
return;
169         }
170         int spaces = level * indentSpaces;
171         if (line>0) {
172             spaces -= column;
173             if (spaces <= 0) {
174                 return; // there's already enough white space, don't add more
175
}
176         }
177         while (spaces >= indentChars.length()) {
178             indentChars += " ";
179         }
180         // output the initial newline character only if line==0
181
int start = (line == 0 ? 0 : 1);
182         super.characters(indentChars.subSequence(start, start+spaces+1), 0, ReceiverOptions.NO_SPECIAL_CHARS);
183         sameline = false;
184     }
185
186 };
187
188 //
189
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
190
// you may not use this file except in compliance with the License. You may obtain a copy of the
191
// License at http://www.mozilla.org/MPL/
192
//
193
// Software distributed under the License is distributed on an "AS IS" basis,
194
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
195
// See the License for the specific language governing rights and limitations under the License.
196
//
197
// The Original Code is: all this file.
198
//
199
// The Initial Developer of the Original Code is Michael H. Kay.
200
//
201
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
202
//
203
// Contributor(s): none.
204
//
205

206
Popular Tags