KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > output > HTMLIndenter


1 package com.icl.saxon.output;
2 import com.icl.saxon.*;
3 import com.icl.saxon.sort.HashMap;
4 import java.io.*;
5 import org.xml.sax.Attributes JavaDoc;
6 import javax.xml.transform.TransformerException JavaDoc;
7
8 /**
9 * HTMLIndenter: This ProxyEmitter indents HTML elements, by adding whitespace
10 * character data where appropriate.
11 * The character data is never added when within an inline element.
12 * The string used for indentation defaults to four spaces, but may be set using the
13 * indent-chars property
14 *
15 * Author Michael Kay (mhkay@iclway.co.uk)
16 */

17
18
19 public class HTMLIndenter extends ProxyEmitter {
20
21     private int level = 0;
22     private int indentSpaces = 3;
23     private String JavaDoc indentChars = " ";
24     private boolean sameLine = false;
25     private boolean isInlineTag = false;
26     private boolean inFormattedTag = false;
27     private boolean afterInline = false;
28     private boolean afterFormatted = true; // to prevent a newline at the start
29

30
31     // the list of inline tags is from the HTML 4.0 (loose) spec. The significance is that we
32
// mustn't add spaces immediately before or after one of these elements.
33

34     private static String JavaDoc[] inlineTags = {
35         "tt", "i", "b", "u", "s", "strike", "big", "small", "em", "strong", "dfn", "code", "samp",
36          "kbd", "var", "cite", "abbr", "acronym", "a", "img", "applet", "object", "font",
37          "basefont", "br", "script", "map", "q", "sub", "sup", "span", "bdo", "iframe", "input",
38          "select", "textarea", "label", "button" };
39
40     private static HashMap inlineTable = new HashMap(203);
41
42     static {
43         for (int j=0; j<inlineTags.length; j++) {
44             inlineTable.set(inlineTags[j]);
45         }
46     }
47
48     private static boolean isInline(String JavaDoc tag) {
49         return inlineTable.get(tag);
50     }
51
52     // Table of preformatted elements
53

54     private static HashMap formattedTable = new HashMap(51);
55
56     static {
57         formattedTable.set("pre");
58         formattedTable.set("script");
59         formattedTable.set("style");
60         formattedTable.set("textarea");
61         formattedTable.set("xmp"); // obsolete but still encountered!
62
}
63
64     private static boolean isFormatted(String JavaDoc tag) {
65         return formattedTable.get(tag);
66     }
67
68
69
70     public HTMLIndenter() {}
71
72
73     /**
74     * Start of document
75     */

76
77     public void startDocument() throws TransformerException JavaDoc {
78         super.startDocument();
79         String JavaDoc s = outputProperties.getProperty(SaxonOutputKeys.INDENT_SPACES);
80         if (s==null) {
81             indentSpaces = 3;
82         } else {
83             try {
84                 indentSpaces = Integer.parseInt(s);
85             } catch (Exception JavaDoc err) {
86                 indentSpaces = 3;
87             }
88         }
89     }
90
91     /**
92     * Output element start tag
93     */

94
95     public void startElement(int nameCode, Attributes JavaDoc atts,
96                              int[] namespaces, int nscount) throws TransformerException JavaDoc {
97         String JavaDoc tag = namePool.getDisplayName(nameCode);
98         isInlineTag = isInline(tag);
99         inFormattedTag = inFormattedTag || isFormatted(tag);
100         if (!isInlineTag && !inFormattedTag &&
101              !afterInline && !afterFormatted) {
102             indent();
103         }
104
105         
106         super.startElement(nameCode, atts, namespaces, nscount);
107         level++;
108         sameLine = true;
109         afterInline = false;
110         afterFormatted = false;
111     }
112
113     /**
114     * Output element end tag
115     */

116     
117     public void endElement(int nameCode) throws TransformerException JavaDoc {
118         level--;
119         String JavaDoc tag = namePool.getDisplayName(nameCode);
120         boolean thisInline = isInline(tag);
121         boolean thisFormatted = isFormatted(tag);
122         if (!thisInline && !thisFormatted && !afterInline &&
123                  !sameLine && !afterFormatted && !inFormattedTag) {
124             indent();
125             afterInline = false;
126             afterFormatted = false;
127         } else {
128             afterInline = thisInline;
129             afterFormatted = thisFormatted;
130         }
131         super.endElement(nameCode);
132         inFormattedTag = inFormattedTag && !thisFormatted;
133         sameLine = false;
134     }
135
136     /**
137     * Output a processing instruction
138     */

139
140     public void processingInstruction(String JavaDoc target, String JavaDoc data) throws TransformerException JavaDoc {
141         super.processingInstruction(target, data);
142     }
143
144     /**
145     * Output character data
146     */

147
148     public void characters(char[] chars, int start, int len) throws TransformerException JavaDoc {
149         if (inFormattedTag) {
150             super.characters(chars, start, len);
151         } else {
152             int lastNL = start;
153         
154             for (int i=start; i<start+len; i++) {
155                 if (chars[i]=='\n' || (i-lastNL > 120 && chars[i]==' ')) {
156                     sameLine = false;
157                     super.characters(chars, lastNL, i-lastNL);
158                     indent();
159                     lastNL = i+1;
160                     while (lastNL<len && chars[lastNL]==' ') lastNL++;
161                 }
162             }
163             if (lastNL<start+len) {
164                 super.characters(chars, lastNL, start+len-lastNL);
165             }
166         }
167         afterInline = false;
168     }
169
170     /**
171     * Output ignorable white space
172     */

173
174     public void ignorableWhitespace(char[] chars, int start, int len) throws TransformerException JavaDoc {
175         // ignore it
176
}
177
178     /**
179     * Output a comment
180     */

181
182     public void comment(char[] chars, int start, int len) throws TransformerException JavaDoc {
183         indent();
184         super.comment(chars, start, len);
185     }
186
187     /**
188     * End of document
189     */

190
191     public void endDocument() throws TransformerException JavaDoc {
192         super.endDocument();
193     }
194
195     /**
196     * Output white space to reflect the current indentation level
197     */

198
199     private void indent() throws TransformerException JavaDoc {
200         int spaces = level * indentSpaces;
201         while (spaces > indentChars.length()) {
202             indentChars += indentChars;
203         }
204         char[] array = new char[spaces + 1];
205         array[0] = '\n';
206         indentChars.getChars(0, spaces, array, 1);
207         super.characters(array, 0, spaces+1);
208         sameLine = false;
209     }
210
211 };
212
213 //
214
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
215
// you may not use this file except in compliance with the License. You may obtain a copy of the
216
// License at http://www.mozilla.org/MPL/
217
//
218
// Software distributed under the License is distributed on an "AS IS" basis,
219
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
220
// See the License for the specific language governing rights and limitations under the License.
221
//
222
// The Original Code is: all this file.
223
//
224
// The Initial Developer of the Original Code is
225
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
226
//
227
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
228
//
229
// Contributor(s): none.
230
//
231

232
Popular Tags