1 package net.sf.saxon.event; 2 3 import net.sf.saxon.om.AttributeCollectionImpl; 4 import net.sf.saxon.om.NamespaceConstant; 5 import net.sf.saxon.trans.DynamicError; 6 import net.sf.saxon.trans.SaxonErrorCode; 7 import net.sf.saxon.trans.XPathException; 8 import net.sf.saxon.type.SchemaException; 9 import net.sf.saxon.value.Whitespace; 10 import org.xml.sax.ContentHandler ; 11 import org.xml.sax.Locator ; 12 import org.xml.sax.SAXException ; 13 import org.xml.sax.ext.LexicalHandler ; 14 15 import javax.xml.transform.Result ; 16 import java.util.Properties ; 17 import java.util.Stack ; 18 19 32 33 public class ContentHandlerProxy extends Emitter implements Locator { 34 protected ContentHandler handler; 35 protected LexicalHandler lexicalHandler; 36 private LocationProvider locationProvider; 37 private int depth = 0; 38 private boolean requireWellFormed = false; 39 private boolean undeclareNamespaces = false; 40 private Stack elementStack = new Stack (); 41 private Stack namespaceStack = new Stack (); 42 protected AttributeCollectionImpl pendingAttributes; 43 private int pendingElement = -1; 44 private int currentLocationId; 45 46 private static final String marker = "##"; 47 48 51 52 public void setUnderlyingContentHandler(ContentHandler handler) { 53 this.handler = handler; 54 if (handler instanceof LexicalHandler ) { 55 this.lexicalHandler = (LexicalHandler )handler; 56 } 57 } 58 59 62 63 public ContentHandler getUnderlyingContentHandler() { 64 return handler; 65 } 66 67 71 72 public void setLexicalHandler(LexicalHandler handler) { 73 this.lexicalHandler = handler; 74 } 75 76 79 80 public void setPipelineConfiguration(PipelineConfiguration config) { 81 super.setPipelineConfiguration(config); 82 this.locationProvider = config.getLocationProvider(); 83 } 84 85 88 89 public void setOutputProperties(Properties details) throws XPathException { 90 String prop = details.getProperty(SaxonOutputKeys.REQUIRE_WELL_FORMED); 91 if (prop != null) { 92 requireWellFormed = prop.equals("yes"); 93 } 94 prop = details.getProperty(SaxonOutputKeys.UNDECLARE_PREFIXES); 95 if (prop != null) { 96 undeclareNamespaces = prop.equals("yes"); 97 } 98 super.setOutputProperties(details); 99 } 100 101 105 106 public boolean isRequireWellFormed() { 107 return requireWellFormed; 108 } 109 110 114 115 public void setRequireWellFormed(boolean wellFormed) { 116 requireWellFormed = wellFormed; 117 } 118 119 125 126 public boolean isUndeclareNamespaces() { 127 return undeclareNamespaces; 128 } 129 130 136 137 public void setUndeclareNamespaces(boolean undeclareNamespaces) { 138 this.undeclareNamespaces = undeclareNamespaces; 139 } 140 141 144 145 public void open() throws XPathException { 146 pendingAttributes = new AttributeCollectionImpl(getPipelineConfiguration().getConfiguration().getNamePool()); 147 if (handler == null) { 148 throw new DynamicError("ContentHandlerProxy.startDocument(): no underlying handler provided"); 149 } 150 try { 151 locationProvider = getPipelineConfiguration().getLocationProvider(); 152 pendingAttributes.setLocationProvider(locationProvider); 153 handler.setDocumentLocator(this); 154 handler.startDocument(); 155 } catch (SAXException err) { 156 throw new DynamicError(err); 157 } 158 depth = 0; 159 } 160 161 164 165 public void close() throws XPathException { 166 try { 167 handler.endDocument(); 168 } catch (SAXException err) { 169 throw new DynamicError(err); 170 } 171 } 172 173 176 177 public void startDocument(int properties) throws XPathException { 178 } 179 180 183 184 public void endDocument() throws XPathException { 185 } 186 187 190 191 public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException { 192 depth++; 193 if (depth <= 0 && requireWellFormed) { 194 notifyNotWellFormed(); 195 } 196 pendingElement = nameCode; 197 currentLocationId = locationId; 198 namespaceStack.push(marker); 199 } 200 201 205 206 public void namespace(int namespaceCode, int properties) throws XPathException { 207 if (namespaceCode == NamespaceConstant.XML_NAMESPACE_CODE) { 208 return; 209 } 210 String prefix = namePool.getPrefixFromNamespaceCode(namespaceCode); 211 String uri = namePool.getURIFromNamespaceCode(namespaceCode); 212 if ((!undeclareNamespaces) && "".equals(uri) && !("".equals(prefix))) { 213 return; 214 } 215 try { 216 handler.startPrefixMapping(prefix, uri); 217 namespaceStack.push(prefix); 218 } catch (SAXException err) { 219 throw new DynamicError(err); 220 } 221 } 222 223 227 228 public void attribute(int nameCode, int typeCode, CharSequence value, int locationId, int properties) 229 throws XPathException { 230 int index = pendingAttributes.getIndexByFingerprint(nameCode & 0xfffff); 231 if (index < 0) { 232 pendingAttributes.addAttribute(nameCode, typeCode, value.toString(), locationId, properties); 233 } else { 234 pendingAttributes.setAttribute(index, nameCode, typeCode, value.toString(), locationId, properties); 235 } 236 } 237 238 244 245 public void startContent() throws XPathException { 246 try { 247 if (depth > 0 || !requireWellFormed) { 248 String uri = namePool.getURI(pendingElement); 249 String localName = namePool.getLocalName(pendingElement); 250 String qname = namePool.getDisplayName(pendingElement); 251 252 handler.startElement(uri, 253 localName, 254 qname, 255 pendingAttributes); 256 257 elementStack.push(uri); 258 elementStack.push(localName); 259 elementStack.push(qname); 260 261 pendingAttributes.clear(); 262 pendingElement = -1; 263 } 264 } catch (SAXException err) { 265 Exception nested = err.getException(); 266 if (nested instanceof XPathException) { 267 throw (XPathException)nested; 268 } else if (nested instanceof SchemaException) { 269 throw new DynamicError(nested); 270 } else { 271 throw new DynamicError(err); 272 } 273 } 274 } 275 276 279 280 public void endElement() throws XPathException { 281 if (depth > 0) { 282 try { 283 String qname = (String )elementStack.pop(); 284 String localName = (String )elementStack.pop(); 285 String uri = (String )elementStack.pop(); 286 handler.endElement(uri, localName, qname); 287 } catch (SAXException err) { 288 throw new DynamicError(err); 289 } 290 } 291 292 while (true) { 293 String prefix = (String )namespaceStack.pop(); 294 if (prefix.equals(marker)) { 295 break; 296 } 297 try { 298 handler.endPrefixMapping(prefix); 299 } catch (SAXException err) { 300 throw new DynamicError(err); 301 } 302 } 303 depth--; 304 if (requireWellFormed && depth <= 0) { 307 depth = Integer.MIN_VALUE; } 309 310 } 311 312 315 316 public void characters(CharSequence chars, int locationId, int properties) throws XPathException { 317 currentLocationId = locationId; 318 boolean disable = ((properties & ReceiverOptions.DISABLE_ESCAPING) != 0); 319 if (disable) { 320 setEscaping(false); 321 } 322 try { 323 if (depth <= 0 && requireWellFormed) { 324 if (Whitespace.isWhite(chars)) { 325 } else { 327 notifyNotWellFormed(); 328 } 329 } else { 330 handler.characters(chars.toString().toCharArray(), 0, chars.length()); 331 } 332 } catch (SAXException err) { 333 throw new DynamicError(err); 334 } 335 if (disable) { 336 setEscaping(true); 337 } 338 } 339 340 344 345 protected void notifyNotWellFormed() throws XPathException { 346 DynamicError err = new DynamicError( 347 "The result tree cannot be supplied to the ContentHandler because it is not well-formed XML"); 348 err.setErrorCode(SaxonErrorCode.SXCH0002); 349 throw err; 350 } 351 352 353 356 357 public void processingInstruction(String target, CharSequence data, int locationId, int properties) 358 throws XPathException { 359 currentLocationId = locationId; 360 try { 361 handler.processingInstruction(target, data.toString()); 362 } catch (SAXException err) { 363 throw new DynamicError(err); 364 } 365 } 366 367 371 372 public void comment(CharSequence chars, int locationId, int properties) 373 throws XPathException { 374 currentLocationId = locationId; 375 try { 376 if (lexicalHandler != null) { 377 lexicalHandler.comment(chars.toString().toCharArray(), 0, chars.length()); 378 } 379 } catch (SAXException err) { 380 throw new DynamicError(err); 381 } 382 } 383 384 385 391 392 private void setEscaping(boolean escaping) { 393 try { 394 handler.processingInstruction((escaping ? Result.PI_ENABLE_OUTPUT_ESCAPING : PI_DISABLE_OUTPUT_ESCAPING), 395 ""); 396 } catch (SAXException err) { 397 } 398 } 399 400 404 408 409 public String getPublicId() { 410 return null; 411 } 412 413 417 418 public String getSystemId() { 419 return locationProvider.getSystemId(currentLocationId); 420 } 421 422 426 427 public int getLineNumber() { 428 return locationProvider.getLineNumber(currentLocationId); 429 } 430 431 435 436 public int getColumnNumber() { 437 return -1; 438 } 439 440 } 441 442 | Popular Tags |