1 package net.sf.saxon.pull; 2 import net.sf.saxon.om.*; 3 import net.sf.saxon.trans.XPathException; 4 5 import java.util.ArrayList ; 6 import java.util.Iterator ; 7 import java.util.List ; 8 9 19 20 public class PullNamespaceReducer extends PullFilter implements NamespaceResolver 21 { 22 23 29 private int[] allNamespaces = new int[50]; private int allNamespacesSize = 0; private int[] countStack = new int[50]; 32 private int depth = 0; 33 private int[] localNamespaces; 34 private int localNamespacesSize = 0; 35 private int nameCode; 37 private NamespaceDeclarations declaredNamespaces; 38 private AttributeCollection attributeCollection; 39 40 44 private int[] pendingUndeclarations = null; 45 46 public PullNamespaceReducer(PullProvider base) { 47 super(base); 48 } 49 50 55 56 public int next() throws XPathException { 57 58 int event = super.next(); 59 60 switch (event) { 61 case START_ELEMENT: 62 startElement(); 63 break; 64 case END_ELEMENT: 65 endElement(); 66 break; 67 case PROCESSING_INSTRUCTION: 68 case ATTRIBUTE: 69 case NAMESPACE: 70 nameCode = super.getNameCode(); 71 break; 72 default: 73 nameCode = -1; 74 } 75 return event; 76 } 77 78 private void startElement() throws XPathException { 79 80 83 90 91 92 94 countStack[depth] = 0; 95 if (++depth >= countStack.length) { 97 int[] newstack = new int[depth*2]; 98 System.arraycopy(countStack, 0, newstack, 0, depth); 99 countStack = newstack; 102 } 104 105 107 NamespaceDeclarations declarations = super.getNamespaceDeclarations(); 108 localNamespaces = declarations.getNamespaceCodes(nsBuffer); 109 localNamespacesSize = 0; 110 for (int i=0; i<localNamespaces.length; i++) { 111 if (localNamespaces[i] == -1) { 112 break; 113 } else { 114 if (isNeeded(localNamespaces[i])) { 115 addGlobalNamespace(localNamespaces[i]); 116 countStack[depth - 1]++; 117 localNamespaces[localNamespacesSize++] = localNamespaces[i]; 118 } 119 } 120 } 121 122 124 125 nameCode = checkProposedPrefix(super.getNameCode(), 0); 126 127 132 134 attributeCollection = super.getAttributes(); 135 boolean modified = false; 136 for (int i=0; i<attributeCollection.getLength(); i++) { 137 int nc = attributeCollection.getNameCode(i); 138 if ((nc & ~NamePool.FP_MASK) != 0) { 139 int newnc = checkProposedPrefix(nc, i+1); 141 if (nc != newnc) { 142 if (!modified) { 143 attributeCollection = copyAttributeCollection(attributeCollection); 144 modified = true; 145 } 146 ((AttributeCollectionImpl)attributeCollection).setAttribute(i, newnc, 147 attributeCollection.getTypeAnnotation(i), 148 attributeCollection.getValue(i), 149 attributeCollection.getLocationId(i), 150 attributeCollection.getProperties(i)); 151 } 152 } 153 } 154 155 156 if (localNamespacesSize < localNamespaces.length) { 157 localNamespaces[localNamespacesSize] = -1; } 159 160 declaredNamespaces = new NamespaceDeclarationsImpl(getNamePool(), localNamespaces); 161 countStack[depth-1] = localNamespacesSize; 162 } 163 164 private int[] nsBuffer = new int[20]; 165 166 private void addLocalNamespace(int nc) { 167 if (localNamespacesSize < localNamespaces.length) { 168 localNamespaces[localNamespacesSize++] = nc; 169 } else { 170 if (localNamespacesSize == 0) { 171 localNamespaces = new int[10]; 172 } else { 173 int[] nc2 = new int[localNamespacesSize*2]; 174 System.arraycopy (localNamespaces, 0, nc2, 0, localNamespacesSize); 175 localNamespaces = nc2; 176 localNamespaces[localNamespacesSize++] = nc; 177 } 178 } 179 addGlobalNamespace(nc); 180 } 181 182 185 186 private boolean isNeeded(int nscode) { 187 if (nscode==NamespaceConstant.XML_NAMESPACE_CODE) { 188 return false; 190 } 191 192 194 if (pendingUndeclarations != null) { 195 for (int p=0; p<pendingUndeclarations.length; p++) { 196 if ((nscode>>16) == (pendingUndeclarations[p]>>16)) { 197 pendingUndeclarations[p] = -1; 198 } 200 } 201 } 202 203 for (int i=allNamespacesSize-1; i>=0; i--) { 204 if (allNamespaces[i]==nscode) { 205 return false; 207 } 208 if ((allNamespaces[i]>>16) == (nscode>>16)) { 209 return true; 211 } 212 } 213 214 return (nscode != NamespaceConstant.NULL_NAMESPACE_CODE); 216 217 218 221 } 232 233 240 241 private int checkProposedPrefix(int nameCode, int seq) { 242 NamePool namePool = getNamePool(); 243 int nscode = namePool.getNamespaceCode(nameCode); 244 if (nscode == -1) { 245 nscode = namePool.allocateNamespaceCode(nameCode); 247 } 248 int nsprefix = nscode>>16; 249 250 for (int i=allNamespacesSize-1; i>=0; i--) { 251 if (nsprefix == (allNamespaces[i]>>16)) { 252 if ((nscode & 0xffff) == (allNamespaces[i] & 0xffff)) { 254 return nameCode; } else { 257 if (i + localNamespacesSize >= allNamespacesSize) { 260 String prefix = getSubstitutePrefix(nscode, seq); 262 263 int newNameCode = namePool.allocate( 264 prefix, 265 namePool.getURI(nameCode), 266 namePool.getLocalName(nameCode)); 267 int newNSCode = namePool.allocateNamespaceCode(newNameCode); 268 addLocalNamespace(newNSCode); 269 return newNameCode; 270 } else { 271 addLocalNamespace(nscode); 273 return nameCode; 274 } 275 } 276 } 277 } 278 if (nscode != NamespaceConstant.NULL_NAMESPACE_CODE) { 280 addLocalNamespace(nscode); 281 } 282 return nameCode; 283 } 284 285 291 292 private String getSubstitutePrefix(int nscode, int seq) { 293 String prefix = getNamePool().getPrefixFromNamespaceCode(nscode); 294 return prefix + '_' + seq; 295 } 296 297 300 301 private void addGlobalNamespace(int nscode) { 302 if (allNamespacesSize+1 >= allNamespaces.length) { 304 int[] newlist = new int[allNamespacesSize*2]; 305 System.arraycopy(allNamespaces, 0, newlist, 0, allNamespacesSize); 306 allNamespaces = newlist; 307 } 308 allNamespaces[allNamespacesSize++] = nscode; 309 } 310 311 325 326 public int getNameCode() { 327 return nameCode; 328 } 329 330 344 345 public AttributeCollection getAttributes() throws XPathException { 346 return attributeCollection; 347 } 348 349 private AttributeCollectionImpl copyAttributeCollection(AttributeCollection in) { 350 AttributeCollectionImpl out = new AttributeCollectionImpl(getNamePool()); 351 for (int i=0; i<in.getLength(); i++) { 352 out.addAttribute(in.getNameCode(i), 353 in.getTypeAnnotation(i), 354 in.getValue(i), 355 in.getLocationId(i), 356 in.getProperties(i)); 357 } 358 return out; 359 } 360 361 380 381 public NamespaceDeclarations getNamespaceDeclarations() throws XPathException { 382 return declaredNamespaces; 383 } 384 385 388 389 390 public void endElement () throws XPathException 391 { 392 if (depth-- == 0) { 393 throw new IllegalStateException ("Attempt to output end tag with no matching start tag"); 394 } 395 396 int nscount = countStack[depth]; 397 allNamespacesSize -= nscount; 398 } 399 400 406 407 protected short getURICode(short prefixCode) { 408 for (int i=allNamespacesSize-1; i>=0; i--) { 409 if ((allNamespaces[i]>>16) == (prefixCode)) { 410 return (short)(allNamespaces[i]&0xffff); 411 } 412 } 413 if (prefixCode == 0) { 414 return 0; } else { 416 return -1; 417 } 418 } 419 420 429 430 public String getURIForPrefix(String prefix, boolean useDefault) { 431 NamePool pool = getNamePool(); 432 if ("".equals(prefix) && !useDefault) { 433 return ""; 434 } else if ("xml".equals(prefix)) { 435 return NamespaceConstant.XML; 436 } else { 437 short prefixCode = pool.getCodeForPrefix(prefix); 438 short uriCode = getURICode(prefixCode); 439 if (uriCode == -1) { 440 return null; 441 } 442 return pool.getURIFromURICode(uriCode); 443 } 444 } 445 446 450 451 public Iterator iteratePrefixes() { 452 NamePool pool = getNamePool(); 453 List prefixes = new ArrayList (allNamespacesSize); 454 for (int i=allNamespacesSize-1; i>=0; i--) { 455 String prefix = pool.getPrefixFromNamespaceCode(allNamespaces[i]); 456 if (!prefixes.contains(prefix)) { 457 prefixes.add(prefix); 458 } 459 } 460 prefixes.add("xml"); 461 return prefixes.iterator(); 462 } 463 464 465 } 466 467 | Popular Tags |