1 package net.sf.saxon.event; 2 import net.sf.saxon.charcode.CharacterSet; 3 import net.sf.saxon.charcode.CharacterSetFactory; 4 import net.sf.saxon.om.FastStringBuffer; 5 import net.sf.saxon.om.XMLChar; 6 import net.sf.saxon.tinytree.CharSlice; 7 import net.sf.saxon.trans.XPathException; 8 9 import javax.xml.transform.OutputKeys ; 10 import java.util.Properties ; 11 import java.util.Stack ; 12 import java.util.StringTokenizer ; 13 14 20 21 22 public class CDATAFilter extends ProxyReceiver { 23 24 private FastStringBuffer buffer = new FastStringBuffer(256); 25 private Stack stack = new Stack (); 26 private int[] nameList; private CharacterSet characterSet; 28 29 32 33 public void setOutputProperties (Properties details) 34 throws XPathException { 35 nameList = getCdataElements(details); 36 characterSet = CharacterSetFactory.getCharacterSet(details, getPipelineConfiguration().getController()); 37 } 38 39 42 43 public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException { 44 flush(buffer); 45 stack.push(new Integer (nameCode & 0xfffff)); 46 super.startElement(nameCode, typeCode, locationId, properties); 47 } 48 49 52 53 public void endElement() throws XPathException { 54 flush(buffer); 55 stack.pop(); 56 super.endElement(); 57 } 58 59 62 63 public void processingInstruction(String target, CharSequence data, int locationId, int properties) throws XPathException { 64 flush(buffer); 65 super.processingInstruction(target, data, locationId, properties); 66 } 67 68 71 72 public void characters(CharSequence chars, int locationId, int properties) throws XPathException { 73 74 if ((properties & ReceiverOptions.DISABLE_ESCAPING) == 0) { 75 buffer.append(chars.toString()); 76 } else { 77 flush(buffer); 80 super.characters(chars, locationId, properties); 81 } 82 } 83 84 87 88 public void comment(CharSequence chars, int locationId, int properties) throws XPathException { 89 flush(buffer); 90 super.comment(chars, locationId, properties); 91 } 92 93 94 98 99 public void flush(FastStringBuffer buffer) throws XPathException { 100 boolean cdata; 101 int end = buffer.length(); 102 if (end==0) return; 103 104 if (stack.isEmpty()) { 105 cdata = false; } else { 107 int fprint = ((Integer )stack.peek()).intValue(); 108 cdata = isCDATA(fprint); 109 } 110 111 if (cdata) { 112 113 116 int start = 0; 117 int k = 0; 118 while ( k < end ) { 119 int next = buffer.charAt(k); 120 int skip = 1; 121 if (XMLChar.isHighSurrogate((char)next)) { 122 next = XMLChar.supplemental((char)next, buffer.charAt(k+1)); 123 skip = 2; 124 } 125 if (characterSet.inCharset(next)) { 126 k++; 127 } else { 128 129 131 char[] array = new char[k-start]; 132 buffer.getChars(start, k, array, 0); 133 flushCDATA(array, k-start); 134 135 while (k < end) { 136 super.characters(buffer.subSequence(k, k+skip), 0, 0); 140 k += skip; 142 next = buffer.charAt(k); 143 skip = 1; 144 if (XMLChar.isHighSurrogate((char)next)) { 145 next = XMLChar.supplemental((char)next, buffer.charAt(k+1)); 146 skip = 2; 147 } 148 if (characterSet.inCharset(next)) { 149 break; 150 } 151 } 152 start=k; 153 } 154 } 155 char[] rest = new char[end-start]; 156 buffer.getChars(start, end, rest, 0); 157 flushCDATA(rest, end-start); 158 159 } else { 160 super.characters(buffer, 0, 0); 164 } 165 166 buffer.setLength(0); 167 168 } 169 170 174 175 private void flushCDATA(char[] array, int len) throws XPathException { 176 super.characters("<![CDATA[", 0, ReceiverOptions.DISABLE_ESCAPING); 177 178 180 int i=0; 181 int doneto=0; 182 while (i<len-2) { 183 if (array[i]==']' && array[i+1]==']' && array[i+2]=='>') { 184 super.characters(new CharSlice(array, doneto, i+2-doneto), 0, ReceiverOptions.DISABLE_ESCAPING); 185 super.characters("]]><![CDATA[", 0, ReceiverOptions.DISABLE_ESCAPING); 186 doneto=i+2; 187 } 188 i++; 189 } 190 super.characters(new CharSlice(array, doneto, len-doneto), 0, ReceiverOptions.DISABLE_ESCAPING); 191 super.characters("]]>", 0, ReceiverOptions.DISABLE_ESCAPING); 192 } 193 194 195 198 199 private boolean isCDATA(int fingerprint) { 200 for (int i=0; i<nameList.length; i++) { 201 if (nameList[i]==fingerprint) return true; 202 } 203 return false; 204 } 205 206 209 210 private int[] getCdataElements(Properties details) { 211 String cdata = details.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS); 212 if (cdata==null) { 213 return new int[0]; 215 } 216 int count=0; 218 StringTokenizer st1 = new StringTokenizer (cdata); 219 while (st1.hasMoreTokens()) { 220 st1.nextToken(); 221 count++; 222 } 223 int[] array = new int[count]; 224 count = 0; 225 StringTokenizer st2 = new StringTokenizer (cdata); 226 while (st2.hasMoreTokens()) { 227 String expandedName = st2.nextToken(); 228 array[count++] = getNamePool().getFingerprintForExpandedName(expandedName); 229 } 230 return array; 231 } 232 233 }; 234 235 253 | Popular Tags |