KickJava   Java API By Example, From Geeks To Geeks.

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


1 package com.icl.saxon.output;
2 import com.icl.saxon.*;
3 import com.icl.saxon.charcode.CharacterSet;
4 import com.icl.saxon.charcode.CharacterSetFactory;
5 import java.util.*;
6 import java.io.*;
7 import java.text.*;
8 import org.xml.sax.Attributes JavaDoc;
9 import javax.xml.transform.OutputKeys JavaDoc;
10 import javax.xml.transform.TransformerException JavaDoc;
11
12 /**
13 * CDATAFilter: This ProxyEmitter converts character data to CDATA sections,
14 * if the character data belongs to one of a set of element types to be handled this way.
15 *
16 * @author Michael Kay (mhkay@iclway.co.uk)
17 */

18
19
20 public class CDATAFilter extends ProxyEmitter {
21
22     private StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
23     private Stack stack = new Stack();
24     private int[] nameList; // fingerprints of cdata elements
25
private CharacterSet characterSet;
26     private boolean disableEscaping = false;
27
28     /**
29     * Output element start tag
30     */

31
32     public void startElement(int nameCode, Attributes JavaDoc atts,
33                              int[] namespaces, int nscount) throws TransformerException JavaDoc {
34         // System.err.println("Start element " + nameCode);
35
flush(buffer);
36         stack.push(new Integer JavaDoc(nameCode & 0xfffff));
37         super.startElement(nameCode, atts, namespaces, nscount);
38     }
39
40     /**
41     * Output element end tag
42     */

43     
44     public void endElement(int nameCode) throws TransformerException JavaDoc {
45         // System.err.println("End element " + nameCode);
46
flush(buffer);
47         stack.pop();
48         super.endElement(nameCode);
49     }
50
51     /**
52     * Output a processing instruction
53     */

54
55     public void processingInstruction(String JavaDoc target, String JavaDoc data) throws TransformerException JavaDoc {
56         flush(buffer);
57         super.processingInstruction(target, data);
58     }
59
60     /**
61     * Output character data
62     */

63
64     public void characters(char[] chars, int start, int len) throws TransformerException JavaDoc {
65         // System.err.println("Characters: '" + new String(chars, start, len) + "'");
66
buffer.append(chars, start, len);
67     }
68
69     /**
70     * Output ignorable white space
71     */

72
73     public void ignorableWhitespace(char[] chars, int start, int len) throws TransformerException JavaDoc {
74         buffer.append(chars, start, len);
75     }
76
77     /**
78     * Output a comment
79     */

80
81     public void comment(char[] chars, int start, int len) throws TransformerException JavaDoc {
82         flush(buffer);
83         super.comment(chars, start, len);
84     }
85
86     /**
87     * Set escaping on or off
88     */

89
90     public void setEscaping(boolean escaping) throws TransformerException JavaDoc {
91         //System.err.println("Set escaping " + escaping);
92
boolean cdata;
93         if (stack.isEmpty()) {
94             cdata = false; // text is not part of any element
95
} else {
96             int fprint = ((Integer JavaDoc)stack.peek()).intValue();
97             cdata = isCDATA(fprint);
98         }
99
100         if (!cdata) {
101             flush(buffer);
102             disableEscaping = !escaping;
103             super.setEscaping(escaping);
104         } else {
105             if (!escaping) {
106                 flush(buffer);
107                 disableEscaping = true;
108                 super.setEscaping(false);
109             } else {
110                 flush(buffer);
111                 disableEscaping = false;
112                 super.setEscaping(true);
113             }
114         }
115     }
116
117     /**
118     * Flush the buffer containing accumulated character data,
119     * generating it as CDATA where appropriate
120     */

121
122     public void flush(StringBuffer JavaDoc buffer) throws TransformerException JavaDoc {
123         boolean cdata;
124         int end = buffer.length();
125         if (end==0) return;
126         
127         if (stack.isEmpty()) {
128             cdata = false; // text is not part of any element
129
} else {
130             int fprint = ((Integer JavaDoc)stack.peek()).intValue();
131             cdata = isCDATA(fprint);
132         }
133         // System.err.println("Flush cdata=" + cdata + " disable=" + disableEscaping + " content=" + buffer);
134
if (cdata & !disableEscaping) {
135
136             // Check that the buffer doesn't include a character not available in the current
137
// encoding
138

139             int start = 0;
140             int k = 0;
141             while ( k<end ) {
142                 if (!characterSet.inCharset(buffer.charAt(k))) {
143
144                     char[] array = new char[k-start];
145                     buffer.getChars(start, k, array, 0);
146                     flushCDATA(array, k-start);
147                     
148                     super.setEscaping(true);
149                     char[] singleton = new char[1];
150                     singleton[0] = buffer.charAt(k);
151                     super.characters(singleton, 0, 1);
152                     super.setEscaping(false);
153
154                     start=k+1;
155                 }
156                 k++;
157             }
158             char[] rest = new char[end-start];
159             buffer.getChars(start, end, rest, 0);
160             flushCDATA(rest, end-start);
161
162         } else {
163             char[] array = new char[end];
164             buffer.getChars(0, end, array, 0);
165             super.characters(array, 0, end);
166         }
167
168         buffer.setLength(0);
169
170     }
171
172     /**
173     * Output an array as a CDATA section. At this stage we have checked that all the characters
174     * are OK, but we haven't checked that there is no "]]>" sequence in the data
175     */

176
177     private void flushCDATA(char[] array, int len) throws TransformerException JavaDoc {
178         super.setEscaping(false);
179         super.characters(("<![CDATA[").toCharArray(), 0, 9);
180
181         // Check that the character data doesn't include the substring "]]>"
182

183         int i=0;
184         int doneto=0;
185         while (i<len-2) {
186             if (array[i]==']' && array[i+1]==']' && array[i+2]=='>') {
187                 super.characters(array, doneto, i+2-doneto);
188                 super.characters(("]]><![CDATA[").toCharArray(), 0, 12);
189                 doneto=i+2;
190             }
191             i++;
192         }
193         super.characters(array, doneto, len-doneto);
194         super.characters(("]]>").toCharArray(), 0, 3);
195         super.setEscaping(true);
196     }
197
198     /**
199     * Set output properties
200     */

201
202     public void setOutputProperties (Properties details) {
203         nameList = getCdataElements(details);
204         characterSet = CharacterSetFactory.getCharacterSet(details);
205         super.setOutputProperties(details);
206     }
207     
208     /**
209     * See if a particular element is a CDATA element
210     */

211     
212     public boolean isCDATA(int fingerprint) {
213         for (int i=0; i<nameList.length; i++) {
214             if (nameList[i]==fingerprint) return true;
215         }
216         return false;
217     }
218
219     /**
220     * Extract the list of CDATA elements from the output properties
221     */

222
223     private int[] getCdataElements(Properties details) {
224         String JavaDoc cdata = details.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS);
225         if (cdata==null) {
226             return new int[0];
227         }
228         // first count the number of names in the list
229
int count=0;
230         StringTokenizer st1 = new StringTokenizer(cdata);
231         while (st1.hasMoreTokens()) {
232             String JavaDoc expandedName = st1.nextToken();
233             count++;
234         }
235         int[] array = new int[count];
236         count = 0;
237         StringTokenizer st2 = new StringTokenizer(cdata);
238         while (st2.hasMoreTokens()) {
239             String JavaDoc expandedName = st2.nextToken();
240             array[count++] = getFingerprintForExpandedName(expandedName);
241         }
242         return array;
243     }
244         
245
246     /**
247     * Get fingerprint for expanded name in {uri}local format
248     */

249
250     private int getFingerprintForExpandedName(String JavaDoc expandedName) {
251         String JavaDoc localName;
252         String JavaDoc namespace;
253
254         if (expandedName.charAt(0)=='{') {
255             int closeBrace = expandedName.indexOf('}');
256             if (closeBrace < 0) {
257                 throw new IllegalArgumentException JavaDoc("No closing '}' in parameter name");
258             }
259             namespace = expandedName.substring(1, closeBrace);
260             if (closeBrace == expandedName.length()) {
261                 throw new IllegalArgumentException JavaDoc("Missing local part in parameter name");
262             }
263             localName = expandedName.substring(closeBrace+1);
264         } else {
265             namespace = "";
266             localName = expandedName;
267         }
268             
269         return namePool.allocate("", namespace, localName);
270     }
271
272
273
274 };
275
276 //
277
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
278
// you may not use this file except in compliance with the License. You may obtain a copy of the
279
// License at http://www.mozilla.org/MPL/
280
//
281
// Software distributed under the License is distributed on an "AS IS" basis,
282
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
283
// See the License for the specific language governing rights and limitations under the License.
284
//
285
// The Original Code is: all this file.
286
//
287
// The Initial Developer of the Original Code is
288
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
289
//
290
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
291
//
292
// Contributor(s): none.
293
//
294

295
Popular Tags