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 ; 9 import javax.xml.transform.OutputKeys ; 10 import javax.xml.transform.TransformerException ; 11 12 18 19 20 public class CDATAFilter extends ProxyEmitter { 21 22 private StringBuffer buffer = new StringBuffer (); 23 private Stack stack = new Stack(); 24 private int[] nameList; private CharacterSet characterSet; 26 private boolean disableEscaping = false; 27 28 31 32 public void startElement(int nameCode, Attributes atts, 33 int[] namespaces, int nscount) throws TransformerException { 34 flush(buffer); 36 stack.push(new Integer (nameCode & 0xfffff)); 37 super.startElement(nameCode, atts, namespaces, nscount); 38 } 39 40 43 44 public void endElement(int nameCode) throws TransformerException { 45 flush(buffer); 47 stack.pop(); 48 super.endElement(nameCode); 49 } 50 51 54 55 public void processingInstruction(String target, String data) throws TransformerException { 56 flush(buffer); 57 super.processingInstruction(target, data); 58 } 59 60 63 64 public void characters(char[] chars, int start, int len) throws TransformerException { 65 buffer.append(chars, start, len); 67 } 68 69 72 73 public void ignorableWhitespace(char[] chars, int start, int len) throws TransformerException { 74 buffer.append(chars, start, len); 75 } 76 77 80 81 public void comment(char[] chars, int start, int len) throws TransformerException { 82 flush(buffer); 83 super.comment(chars, start, len); 84 } 85 86 89 90 public void setEscaping(boolean escaping) throws TransformerException { 91 boolean cdata; 93 if (stack.isEmpty()) { 94 cdata = false; } else { 96 int fprint = ((Integer )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 121 122 public void flush(StringBuffer buffer) throws TransformerException { 123 boolean cdata; 124 int end = buffer.length(); 125 if (end==0) return; 126 127 if (stack.isEmpty()) { 128 cdata = false; } else { 130 int fprint = ((Integer )stack.peek()).intValue(); 131 cdata = isCDATA(fprint); 132 } 133 if (cdata & !disableEscaping) { 135 136 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 176 177 private void flushCDATA(char[] array, int len) throws TransformerException { 178 super.setEscaping(false); 179 super.characters(("<![CDATA[").toCharArray(), 0, 9); 180 181 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 201 202 public void setOutputProperties (Properties details) { 203 nameList = getCdataElements(details); 204 characterSet = CharacterSetFactory.getCharacterSet(details); 205 super.setOutputProperties(details); 206 } 207 208 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 222 223 private int[] getCdataElements(Properties details) { 224 String cdata = details.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS); 225 if (cdata==null) { 226 return new int[0]; 227 } 228 int count=0; 230 StringTokenizer st1 = new StringTokenizer(cdata); 231 while (st1.hasMoreTokens()) { 232 String 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 expandedName = st2.nextToken(); 240 array[count++] = getFingerprintForExpandedName(expandedName); 241 } 242 return array; 243 } 244 245 246 249 250 private int getFingerprintForExpandedName(String expandedName) { 251 String localName; 252 String namespace; 253 254 if (expandedName.charAt(0)=='{') { 255 int closeBrace = expandedName.indexOf('}'); 256 if (closeBrace < 0) { 257 throw new IllegalArgumentException ("No closing '}' in parameter name"); 258 } 259 namespace = expandedName.substring(1, closeBrace); 260 if (closeBrace == expandedName.length()) { 261 throw new IllegalArgumentException ("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 295 | Popular Tags |