1 /******************************************************************************* 2 3 Copyright: Copyright (C) 2007-2008 Scott Sanders, Kris Bell. 4 All rights reserved. 5 6 License: BSD style: $(LICENSE) 7 8 version: Initial release: February 2008 9 10 Authors: stonecobra, Kris 11 12 Acknowledgements: 13 Many thanks to the entire group that came up with 14 SAX as an API, and then had the foresight to place 15 it into the public domain so that it can become a 16 de-facto standard. It may not be the best XML API, 17 but it sure is handy. For more information, see 18 <a href='http://www.saxproject.org'>http://www.saxproject.org</a>. 19 20 *******************************************************************************/ 21 22 module tango.text.xml.SaxParser; 23 24 private import tango.io.model.IConduit; 25 private import tango.text.xml.PullParser; 26 27 /******************************************************************************* 28 29 Single attributes are represented by this struct. 30 31 *******************************************************************************/ 32 struct Attribute(Ch = char) { 33 34 const(Ch)[] localName; 35 const(Ch)[] value; 36 37 } 38 39 /******************************************************************************* 40 * Receive notification of the logical content of a document. 41 * 42 * <p>This is the main interface that most SAX applications 43 * implement: if the application needs to be informed of basic parsing 44 * events, it implements this interface and registers an instance with 45 * the SAX parser using the {@link org.xml.sax.XMLReader#setContentHandler 46 * setContentHandler} method. The parser uses the instance to report 47 * basic document-related events like the start and end of elements 48 * and character data.</p> 49 * 50 * <p>The order of events in this interface is very important, and 51 * mirrors the order of information in the document itself. For 52 * example, all of an element's content (character data, processing 53 * instructions, and/or subelements) will appear, in order, between 54 * the startElement event and the corresponding endElement event.</p> 55 * 56 * <p>This interface is similar to the now-deprecated SAX 1.0 57 * DocumentHandler interface, but it adds support for Namespaces 58 * and for reporting skipped entities (in non-validating XML 59 * processors).</p> 60 * 61 * <p>Implementors should note that there is also a 62 * <code>ContentHandler</code> class in the <code>java.net</code> 63 * package; that means that it's probably a bad idea to do</p> 64 * 65 * <pre>import java.net.*; 66 * import org.xml.sax.*; 67 * </pre> 68 * 69 * <p>In fact, "import ...*" is usually a sign of sloppy programming 70 * anyway, so the user should consider this a feature rather than a 71 * bug.</p> 72 * 73 * @since SAX 2.0 74 * @author David Megginson 75 * @version 2.0.1+ (sax2r3pre1) 76 * @see org.xml.sax.XMLReader 77 * @see org.xml.sax.ErrorHandler 78 *******************************************************************************/ 79 public class SaxHandler(Ch = char) { 80 81 Locator!(Ch) locator; 82 83 /******************************************************************************* 84 * Receive an object for locating the origin of SAX document events. 85 * 86 * <p>SAX parsers are strongly encouraged (though not absolutely 87 * required) to supply a locator: if it does so, it must supply 88 * the locator to the application by invoking this method before 89 * invoking any of the other methods in the ContentHandler 90 * interface.</p> 91 * 92 * <p>The locator allows the application to determine the end 93 * position of any document-related event, even if the parser is 94 * not reporting an error. Typically, the application will 95 * use this information for reporting its own errors (such as 96 * character content that does not match an application's 97 * business rules). The information returned by the locator 98 * is probably not sufficient for use with a search engine.</p> 99 * 100 * <p>Note that the locator will return correct information only 101 * during the invocation SAX event callbacks after 102 * {@link #startDocument startDocument} returns and before 103 * {@link #endDocument endDocument} is called. The 104 * application should not attempt to use it at any other time.</p> 105 * 106 * @param locator an object that can return the location of 107 * any SAX document event 108 * @see org.xml.sax.Locator 109 *******************************************************************************/ 110 public void setDocumentLocator(Locator!(Ch) locator) 111 { 112 this.locator = locator; 113 } 114 115 /******************************************************************************* 116 * Receive notification of the beginning of a document. 117 * 118 * <p>The SAX parser will invoke this method only once, before any 119 * other event callbacks (except for {@link #setDocumentLocator 120 * setDocumentLocator}).</p> 121 * 122 * @throws org.xml.sax.SAXException any SAX exception, possibly 123 * wrapping another exception 124 * @see #endDocument 125 *******************************************************************************/ 126 public void startDocument() 127 { 128 129 } 130 131 /******************************************************************************* 132 * Receive notification of the end of a document. 133 * 134 * <p><strong>There is an apparent contradiction between the 135 * documentation for this method and the documentation for {@link 136 * org.xml.sax.ErrorHandler#fatalError}. Until this ambiguity is 137 * resolved in a future major release, clients should make no 138 * assumptions about whether endDocument() will or will not be 139 * invoked when the parser has reported a fatalError() or thrown 140 * an exception.</strong></p> 141 * 142 * <p>The SAX parser will invoke this method only once, and it will 143 * be the last method invoked during the parse. The parser shall 144 * not invoke this method until it has either abandoned parsing 145 * (because of an unrecoverable error) or reached the end of 146 * input.</p> 147 * 148 * @throws org.xml.sax.SAXException any SAX exception, possibly 149 * wrapping another exception 150 * @see #startDocument 151 *******************************************************************************/ 152 public void endDocument() 153 { 154 155 } 156 157 /******************************************************************************* 158 * Begin the scope of a prefix-URI Namespace mapping. 159 * 160 * <p>The information from this event is not necessary for 161 * normal Namespace processing: the SAX XML reader will 162 * automatically replace prefixes for element and attribute 163 * names when the <code>http://xml.org/sax/features/namespaces</code> 164 * feature is <var>true</var> (the default).</p> 165 * 166 * <p>There are cases, however, when applications need to 167 * use prefixes in character data or in attribute values, 168 * where they cannot safely be expanded automatically; the 169 * start/endPrefixMapping event supplies the information 170 * to the application to expand prefixes in those contexts 171 * itself, if necessary.</p> 172 * 173 * <p>Note that start/endPrefixMapping events are not 174 * guaranteed to be properly nested relative to each other: 175 * all startPrefixMapping events will occur immediately before the 176 * corresponding {@link #startElement startElement} event, 177 * and all {@link #endPrefixMapping endPrefixMapping} 178 * events will occur immediately after the corresponding 179 * {@link #endElement endElement} event, 180 * but their order is not otherwise 181 * guaranteed.</p> 182 * 183 * <p>There should never be start/endPrefixMapping events for the 184 * "xml" prefix, since it is predeclared and immutable.</p> 185 * 186 * @param prefix the Namespace prefix being declared. 187 * An empty string is used for the default element namespace, 188 * which has no prefix. 189 * @param uri the Namespace URI the prefix is mapped to 190 * @throws org.xml.sax.SAXException the client may throw 191 * an exception during processing 192 * @see #endPrefixMapping 193 * @see #startElement 194 *******************************************************************************/ 195 public void startPrefixMapping(const(Ch)[] prefix, const(Ch)[] uri) 196 { 197 198 } 199 200 /******************************************************************************* 201 * End the scope of a prefix-URI mapping. 202 * 203 * <p>See {@link #startPrefixMapping startPrefixMapping} for 204 * details. These events will always occur immediately after the 205 * corresponding {@link #endElement endElement} event, but the order of 206 * {@link #endPrefixMapping endPrefixMapping} events is not otherwise 207 * guaranteed.</p> 208 * 209 * @param prefix the prefix that was being mapped. 210 * This is the empty string when a default mapping scope ends. 211 * @throws org.xml.sax.SAXException the client may throw 212 * an exception during processing 213 * @see #startPrefixMapping 214 * @see #endElement 215 *******************************************************************************/ 216 public void endPrefixMapping(const(Ch)[] prefix) 217 { 218 219 } 220 221 /******************************************************************************* 222 * Receive notification of the beginning of an element. 223 * 224 * <p>The Parser will invoke this method at the beginning of every 225 * element in the XML document; there will be a corresponding 226 * {@link #endElement endElement} event for every startElement event 227 * (even when the element is empty). All of the element's content will be 228 * reported, in order, before the corresponding endElement 229 * event.</p> 230 * 231 * <p>This event allows up to three name components for each 232 * element:</p> 233 * 234 * <ol> 235 * <li>the Namespace URI;</li> 236 * <li>the local name; and</li> 237 * <li>the qualified (prefixed) name.</li> 238 * </ol> 239 * 240 * <p>Any or all of these may be provided, depending on the 241 * values of the <var>http://xml.org/sax/features/namespaces</var> 242 * and the <var>http://xml.org/sax/features/namespace-prefixes</var> 243 * properties:</p> 244 * 245 * <ul> 246 * <li>the Namespace URI and local name are required when 247 * the namespaces property is <var>true</var> (the default), and are 248 * optional when the namespaces property is <var>false</var> (if one is 249 * specified, both must be);</li> 250 * <li>the qualified name is required when the namespace-prefixes property 251 * is <var>true</var>, and is optional when the namespace-prefixes property 252 * is <var>false</var> (the default).</li> 253 * </ul> 254 * 255 * <p>Note that the attribute list provided will contain only 256 * attributes with explicit values (specified or defaulted): 257 * #IMPLIED attributes will be omitted. The attribute list 258 * will contain attributes used for Namespace declarations 259 * (xmlns* attributes) only if the 260 * <code>http://xml.org/sax/features/namespace-prefixes</code> 261 * property is true (it is false by default, and support for a 262 * true value is optional).</p> 263 * 264 * <p>Like {@link #characters characters()}, attribute values may have 265 * characters that need more than one <code>char</code> value. </p> 266 * 267 * @param uri the Namespace URI, or the empty string if the 268 * element has no Namespace URI or if Namespace 269 * processing is not being performed 270 * @param localName the local name (without prefix), or the 271 * empty string if Namespace processing is not being 272 * performed 273 * @param qName the qualified name (with prefix), or the 274 * empty string if qualified names are not available 275 * @param atts the attributes attached to the element. If 276 * there are no attributes, it shall be an empty 277 * Attributes object. The value of this object after 278 * startElement returns is undefined 279 * @throws org.xml.sax.SAXException any SAX exception, possibly 280 * wrapping another exception 281 * @see #endElement 282 * @see org.xml.sax.Attributes 283 * @see org.xml.sax.helpers.AttributesImpl 284 *******************************************************************************/ 285 public void startElement(const(Ch)[] uri, const(Ch)[] localName, const(Ch)[] qName, Attribute!(Ch)[] atts) 286 { 287 288 } 289 290 /******************************************************************************* 291 * Receive notification of the end of an element. 292 * 293 * <p>The SAX parser will invoke this method at the end of every 294 * element in the XML document; there will be a corresponding 295 * {@link #startElement startElement} event for every endElement 296 * event (even when the element is empty).</p> 297 * 298 * <p>For information on the names, see startElement.</p> 299 * 300 * @param uri the Namespace URI, or the empty string if the 301 * element has no Namespace URI or if Namespace 302 * processing is not being performed 303 * @param localName the local name (without prefix), or the 304 * empty string if Namespace processing is not being 305 * performed 306 * @param qName the qualified XML name (with prefix), or the 307 * empty string if qualified names are not available 308 * @throws org.xml.sax.SAXException any SAX exception, possibly 309 * wrapping another exception 310 *******************************************************************************/ 311 public void endElement(const(Ch)[] uri, const(Ch)[] localName, const(Ch)[] qName) 312 { 313 314 } 315 316 /******************************************************************************* 317 * Receive notification of character data. 318 * 319 * <p>The Parser will call this method to report each chunk of 320 * character data. SAX parsers may return all contiguous character 321 * data in a single chunk, or they may split it into several 322 * chunks; however, all of the characters in any single event 323 * must come from the same external entity so that the Locator 324 * provides useful information.</p> 325 * 326 * <p>The application must not attempt to read from the array 327 * outside of the specified range.</p> 328 * 329 * <p>Individual characters may consist of more than one Java 330 * <code>char</code> value. There are two important cases where this 331 * happens, because characters can't be represented in just sixteen bits. 332 * In one case, characters are represented in a <em>Surrogate Pair</em>, 333 * using two special Unicode values. Such characters are in the so-called 334 * "Astral Planes", with a code point above U+FFFF. A second case involves 335 * composite characters, such as a base character combining with one or 336 * more accent characters. </p> 337 * 338 * <p> Your code should not assume that algorithms using 339 * <code>char</code>-at-a-time idioms will be working in character 340 * units; in some cases they will split characters. This is relevant 341 * wherever XML permits arbitrary characters, such as attribute values, 342 * processing instruction data, and comments as well as in data reported 343 * from this method. It's also generally relevant whenever Java code 344 * manipulates internationalized text; the issue isn't unique to XML.</p> 345 * 346 * <p>Note that some parsers will report whitespace in element 347 * content using the {@link #ignorableWhitespace ignorableWhitespace} 348 * method rather than this one (validating parsers <em>must</em> 349 * do so).</p> 350 * 351 * @param ch the characters from the XML document 352 * @param start the start position in the array 353 * @param length the number of characters to read from the array 354 * @throws org.xml.sax.SAXException any SAX exception, possibly 355 * wrapping another exception 356 * @see #ignorableWhitespace 357 * @see org.xml.sax.Locator 358 *******************************************************************************/ 359 public void characters(const(Ch)[] ch) 360 { 361 362 } 363 364 /******************************************************************************* 365 * Receive notification of ignorable whitespace in element content. 366 * 367 * <p>Validating Parsers must use this method to report each chunk 368 * of whitespace in element content (see the W3C XML 1.0 369 * recommendation, section 2.10): non-validating parsers may also 370 * use this method if they are capable of parsing and using 371 * content models.</p> 372 * 373 * <p>SAX parsers may return all contiguous whitespace in a single 374 * chunk, or they may split it into several chunks; however, all of 375 * the characters in any single event must come from the same 376 * external entity, so that the Locator provides useful 377 * information.</p> 378 * 379 * <p>The application must not attempt to read from the array 380 * outside of the specified range.</p> 381 * 382 * @param ch the characters from the XML document 383 * @param start the start position in the array 384 * @param length the number of characters to read from the array 385 * @throws org.xml.sax.SAXException any SAX exception, possibly 386 * wrapping another exception 387 * @see #characters 388 *******************************************************************************/ 389 public void ignorableWhitespace(Ch[] ch) 390 { 391 392 } 393 394 /******************************************************************************* 395 * Receive notification of a processing instruction. 396 * 397 * <p>The Parser will invoke this method once for each processing 398 * instruction found: note that processing instructions may occur 399 * before or after the main document element.</p> 400 * 401 * <p>A SAX parser must never report an XML declaration (XML 1.0, 402 * section 2.8) or a text declaration (XML 1.0, section 4.3.1) 403 * using this method.</p> 404 * 405 * <p>Like {@link #characters characters()}, processing instruction 406 * data may have characters that need more than one <code>char</code> 407 * value. </p> 408 * 409 * @param target the processing instruction target 410 * @param data the processing instruction data, or null if 411 * none was supplied. The data does not include any 412 * whitespace separating it from the target 413 * @throws org.xml.sax.SAXException any SAX exception, possibly 414 * wrapping another exception 415 *******************************************************************************/ 416 public void processingInstruction(const(Ch)[] target, const(Ch)[] data) 417 { 418 419 } 420 421 /******************************************************************************* 422 * Receive notification of a skipped entity. 423 * This is not called for entity references within markup constructs 424 * such as element start tags or markup declarations. (The XML 425 * recommendation requires reporting skipped external entities. 426 * SAX also reports internal entity expansion/non-expansion, except 427 * within markup constructs.) 428 * 429 * <p>The Parser will invoke this method each time the entity is 430 * skipped. Non-validating processors may skip entities if they 431 * have not seen the declarations (because, for example, the 432 * entity was declared in an external DTD subset). All processors 433 * may skip external entities, depending on the values of the 434 * <code>http://xml.org/sax/features/external-general-entities</code> 435 * and the 436 * <code>http://xml.org/sax/features/external-parameter-entities</code> 437 * properties.</p> 438 * 439 * @param name the name of the skipped entity. If it is a 440 * parameter entity, the name will begin with '%', and if 441 * it is the external DTD subset, it will be the string 442 * "[dtd]" 443 * @throws org.xml.sax.SAXException any SAX exception, possibly 444 * wrapping another exception 445 *******************************************************************************/ 446 public void skippedEntity(const(Ch)[] name) 447 { 448 449 } 450 451 } 452 453 /******************************************************************************* 454 * Basic interface for resolving entities. 455 * 456 * <p>If a SAX application needs to implement customized handling 457 * for external entities, it must implement this interface and 458 * register an instance with the SAX driver using the 459 * {@link org.xml.sax.XMLReader#setEntityResolver setEntityResolver} 460 * method.</p> 461 * 462 * <p>The XML reader will then allow the application to intercept any 463 * external entities (including the external DTD subset and external 464 * parameter entities, if any) before including them.</p> 465 * 466 * <p>Many SAX applications will not need to implement this interface, 467 * but it will be especially useful for applications that build 468 * XML documents from databases or other specialised input sources, 469 * or for applications that use URI types other than URLs.</p> 470 * 471 * <p>The following resolver would provide the application 472 * with a special character stream for the entity with the system 473 * identifier "http://www.myhost.com/today":</p> 474 * 475 * <pre> 476 * import org.xml.sax.EntityResolver; 477 * import org.xml.sax.InputSource; 478 * 479 * public class MyResolver implements EntityResolver { 480 * public InputSource resolveEntity (String publicId, String systemId) 481 * { 482 * if (systemId.equals("http://www.myhost.com/today")) { 483 * // return a special input source 484 * MyReader reader = new MyReader(); 485 * return new InputSource(reader); 486 * } else { 487 * // use the default behaviour 488 * return null; 489 * } 490 * } 491 * } 492 * </pre> 493 * 494 * <p>The application can also use this interface to redirect system 495 * identifiers to local URIs or to look up replacements in a catalog 496 * (possibly by using the public identifier).</p> 497 * 498 * @since SAX 1.0 499 * @author David Megginson 500 * @version 2.0.1 (sax2r2) 501 * @see org.xml.sax.XMLReader#setEntityResolver 502 * @see org.xml.sax.InputSource 503 *******************************************************************************/ 504 public interface EntityResolver(Ch = char) { 505 506 /******************************************************************************* 507 * Allow the application to resolve external entities. 508 * 509 * <p>The parser will call this method before opening any external 510 * entity except the top-level document entity. Such entities include 511 * the external DTD subset and external parameter entities referenced 512 * within the DTD (in either case, only if the parser reads external 513 * parameter entities), and external general entities referenced 514 * within the document element (if the parser reads external general 515 * entities). The application may request that the parser locate 516 * the entity itself, that it use an alternative URI, or that it 517 * use data provided by the application (as a character or byte 518 * input stream).</p> 519 * 520 * <p>Application writers can use this method to redirect external 521 * system identifiers to secure and/or local URIs, to look up 522 * public identifiers in a catalogue, or to read an entity from a 523 * database or other input source (including, for example, a dialog 524 * box). Neither XML nor SAX specifies a preferred policy for using 525 * public or system IDs to resolve resources. However, SAX specifies 526 * how to interpret any InputSource returned by this method, and that 527 * if none is returned, then the system ID will be dereferenced as 528 * a URL. </p> 529 * 530 * <p>If the system identifier is a URL, the SAX parser must 531 * resolve it fully before reporting it to the application.</p> 532 * 533 * @param publicId The public identifier of the external entity 534 * being referenced, or null if none was supplied. 535 * @param systemId The system identifier of the external entity 536 * being referenced. 537 * @return An InputSource object describing the new input source, 538 * or null to request that the parser open a regular 539 * URI connection to the system identifier. 540 * @exception org.xml.sax.SAXException Any SAX exception, possibly 541 * wrapping another exception. 542 * @exception java.io.IOException A Java-specific IO exception, 543 * possibly the result of creating a new InputStream 544 * or Reader for the InputSource. 545 * @see org.xml.sax.InputSource 546 *******************************************************************************/ 547 548 public InputStream resolveEntity(const(Ch)[] publicId, const(Ch)[] systemId); 549 550 } 551 552 /******************************************************************************* 553 * Basic interface for SAX error handlers. 554 * 555 * <p>If a SAX application needs to implement customized error 556 * handling, it must implement this interface and then register an 557 * instance with the XML reader using the 558 * {@link org.xml.sax.XMLReader#setErrorHandler setErrorHandler} 559 * method. The parser will then report all errors and warnings 560 * through this interface.</p> 561 * 562 * <p><strong>WARNING:</strong> If an application does <em>not</em> 563 * register an ErrorHandler, XML parsing errors will go unreported, 564 * except that <em>SAXParseException</em>s will be thrown for fatal errors. 565 * In order to detect validity errors, an ErrorHandler that does something 566 * with {@link #error error()} calls must be registered.</p> 567 * 568 * <p>For XML processing errors, a SAX driver must use this interface 569 * in preference to throwing an exception: it is up to the application 570 * to decide whether to throw an exception for different types of 571 * errors and warnings. Note, however, that there is no requirement that 572 * the parser continue to report additional errors after a call to 573 * {@link #fatalError fatalError}. In other words, a SAX driver class 574 * may throw an exception after reporting any fatalError. 575 * Also parsers may throw appropriate exceptions for non-XML errors. 576 * For example, {@link XMLReader#parse XMLReader.parse()} would throw 577 * an IOException for errors accessing entities or the document.</p> 578 * 579 * @since SAX 1.0 580 * @author David Megginson 581 * @version 2.0.1+ (sax2r3pre1) 582 * @see org.xml.sax.XMLReader#setErrorHandler 583 * @see org.xml.sax.SAXParseException 584 *******************************************************************************/ 585 public interface ErrorHandler(Ch = char) { 586 587 /******************************************************************************* 588 * Receive notification of a warning. 589 * 590 * <p>SAX parsers will use this method to report conditions that 591 * are not errors or fatal errors as defined by the XML 592 * recommendation. The default behaviour is to take no 593 * action.</p> 594 * 595 * <p>The SAX parser must continue to provide normal parsing events 596 * after invoking this method: it should still be possible for the 597 * application to process the document through to the end.</p> 598 * 599 * <p>Filters may use this method to report other, non-XML warnings 600 * as well.</p> 601 * 602 * @param exception The warning information encapsulated in a 603 * SAX parse exception. 604 * @exception org.xml.sax.SAXException Any SAX exception, possibly 605 * wrapping another exception. 606 * @see org.xml.sax.SAXParseException 607 *******************************************************************************/ 608 public void warning(SAXException exception); 609 610 /******************************************************************************* 611 * Receive notification of a recoverable error. 612 * 613 * <p>This corresponds to the definition of "error" in section 1.2 614 * of the W3C XML 1.0 Recommendation. For example, a validating 615 * parser would use this callback to report the violation of a 616 * validity constraint. The default behaviour is to take no 617 * action.</p> 618 * 619 * <p>The SAX parser must continue to provide normal parsing 620 * events after invoking this method: it should still be possible 621 * for the application to process the document through to the end. 622 * If the application cannot do so, then the parser should report 623 * a fatal error even if the XML recommendation does not require 624 * it to do so.</p> 625 * 626 * <p>Filters may use this method to report other, non-XML errors 627 * as well.</p> 628 * 629 * @param exception The error information encapsulated in a 630 * SAX parse exception. 631 * @exception org.xml.sax.SAXException Any SAX exception, possibly 632 * wrapping another exception. 633 * @see org.xml.sax.SAXParseException 634 *******************************************************************************/ 635 public void error(SAXException exception); 636 637 /******************************************************************************* 638 * Receive notification of a non-recoverable error. 639 * 640 * <p><strong>There is an apparent contradiction between the 641 * documentation for this method and the documentation for {@link 642 * org.xml.sax.ContentHandler#endDocument}. Until this ambiguity 643 * is resolved in a future major release, clients should make no 644 * assumptions about whether endDocument() will or will not be 645 * invoked when the parser has reported a fatalError() or thrown 646 * an exception.</strong></p> 647 * 648 * <p>This corresponds to the definition of "fatal error" in 649 * section 1.2 of the W3C XML 1.0 Recommendation. For example, a 650 * parser would use this callback to report the violation of a 651 * well-formedness constraint.</p> 652 * 653 * <p>The application must assume that the document is unusable 654 * after the parser has invoked this method, and should continue 655 * (if at all) only for the sake of collecting additional error 656 * messages: in fact, SAX parsers are free to stop reporting any 657 * other events once this method has been invoked.</p> 658 * 659 * @param exception The error information encapsulated in a 660 * SAX parse exception. 661 * @exception org.xml.sax.SAXException Any SAX exception, possibly 662 * wrapping another exception. 663 * @see org.xml.sax.SAXParseException 664 *******************************************************************************/ 665 public void fatalError(SAXException exception); 666 667 } 668 669 /******************************************************************************* 670 * Interface for associating a SAX event with a document location. 671 * 672 * <p>If a SAX parser provides location information to the SAX 673 * application, it does so by implementing this interface and then 674 * passing an instance to the application using the content 675 * handler's {@link org.xml.sax.ContentHandler#setDocumentLocator 676 * setDocumentLocator} method. The application can use the 677 * object to obtain the location of any other SAX event 678 * in the XML source document.</p> 679 * 680 * <p>Note that the results returned by the object will be valid only 681 * during the scope of each callback method: the application 682 * will receive unpredictable results if it attempts to use the 683 * locator at any other time, or after parsing completes.</p> 684 * 685 * <p>SAX parsers are not required to supply a locator, but they are 686 * very strongly encouraged to do so. If the parser supplies a 687 * locator, it must do so before reporting any other document events. 688 * If no locator has been set by the time the application receives 689 * the {@link org.xml.sax.ContentHandler#startDocument startDocument} 690 * event, the application should assume that a locator is not 691 * available.</p> 692 * 693 * @since SAX 1.0 694 * @author David Megginson 695 * @version 2.0.1 (sax2r2) 696 * @see org.xml.sax.ContentHandler#setDocumentLocator 697 *******************************************************************************/ 698 public interface Locator(Ch = char) { 699 700 /******************************************************************************* 701 * Return the public identifier for the current document event. 702 * 703 * <p>The return value is the public identifier of the document 704 * entity or of the external parsed entity in which the markup 705 * triggering the event appears.</p> 706 * 707 * @return A string containing the public identifier, or 708 * null if none is available. 709 * @see #getSystemId 710 *******************************************************************************/ 711 public const(Ch)[] getPublicId(); 712 713 /******************************************************************************* 714 * Return the system identifier for the current document event. 715 * 716 * <p>The return value is the system identifier of the document 717 * entity or of the external parsed entity in which the markup 718 * triggering the event appears.</p> 719 * 720 * <p>If the system identifier is a URL, the parser must resolve it 721 * fully before passing it to the application. For example, a file 722 * name must always be provided as a <em>file:...</em> URL, and other 723 * kinds of relative URI are also resolved against their bases.</p> 724 * 725 * @return A string containing the system identifier, or null 726 * if none is available. 727 * @see #getPublicId 728 *******************************************************************************/ 729 public const(Ch)[] getSystemId(); 730 731 /******************************************************************************* 732 * Return the line number where the current document event ends. 733 * Lines are delimited by line ends, which are defined in 734 * the XML specification. 735 * 736 * <p><strong>Warning:</strong> The return value from the method 737 * is intended only as an approximation for the sake of diagnostics; 738 * it is not intended to provide sufficient information 739 * to edit the character content of the original XML document. 740 * In some cases, these "line" numbers match what would be displayed 741 * as columns, and in others they may not match the source text 742 * due to internal entity expansion. </p> 743 * 744 * <p>The return value is an approximation of the line number 745 * in the document entity or external parsed entity where the 746 * markup triggering the event appears.</p> 747 * 748 * <p>If possible, the SAX driver should provide the line position 749 * of the first character after the text associated with the document 750 * event. The first line is line 1.</p> 751 * 752 * @return The line number, or -1 if none is available. 753 * @see #getColumnNumber 754 *******************************************************************************/ 755 public int getLineNumber(); 756 757 /******************************************************************************* 758 * Return the column number where the current document event ends. 759 * This is one-based number of Java <code>char</code> values since 760 * the last line end. 761 * 762 * <p><strong>Warning:</strong> The return value from the method 763 * is intended only as an approximation for the sake of diagnostics; 764 * it is not intended to provide sufficient information 765 * to edit the character content of the original XML document. 766 * For example, when lines contain combining character sequences, wide 767 * characters, surrogate pairs, or bi-directional text, the value may 768 * not correspond to the column in a text editor's display. </p> 769 * 770 * <p>The return value is an approximation of the column number 771 * in the document entity or external parsed entity where the 772 * markup triggering the event appears.</p> 773 * 774 * <p>If possible, the SAX driver should provide the line position 775 * of the first character after the text associated with the document 776 * event. The first column in each line is column 1.</p> 777 * 778 * @return The column number, or -1 if none is available. 779 * @see #getLineNumber 780 *******************************************************************************/ 781 public int getColumnNumber(); 782 783 } 784 785 786 /******************************************************************************* 787 * Encapsulate a general SAX error or warning. 788 * 789 * <p>This class can contain basic error or warning information from 790 * either the XML parser or the application: a parser writer or 791 * application writer can subclass it to provide additional 792 * functionality. SAX handlers may throw this exception or 793 * any exception subclassed from it.</p> 794 * 795 * <p>If the application needs to pass through other types of 796 * exceptions, it must wrap those exceptions in a SAXException 797 * or an exception derived from a SAXException.</p> 798 * 799 * <p>If the parser or application needs to include information about a 800 * specific location in an XML document, it should use the 801 * {@link org.xml.sax.SAXParseException SAXParseException} subclass.</p> 802 * 803 * @since SAX 1.0 804 * @author David Megginson 805 * @version 2.0.1 (sax2r2) 806 * @see org.xml.sax.SAXParseException 807 *******************************************************************************/ 808 public class SAXException : Exception { 809 810 /******************************************************************************* 811 * Create a new SAXException. 812 *******************************************************************************/ 813 public this () { 814 super ("", cast(Throwable)null); 815 } 816 817 /******************************************************************************* 818 * Create a new SAXException. 819 * 820 * @param message The error or warning message. 821 *******************************************************************************/ 822 public this (immutable(char)[] message) { 823 super (message, cast(Throwable)null); 824 } 825 826 /******************************************************************************* 827 * Create a new SAXException wrapping an existing exception. 828 * 829 * <p>The existing exception will be embedded in the new 830 * one, and its message will become the default message for 831 * the SAXException.</p> 832 * 833 * @param e The exception to be wrapped in a SAXException. 834 *******************************************************************************/ 835 public this (Exception e) { 836 super ("", e); 837 } 838 839 /******************************************************************************* 840 * Create a new SAXException from an existing exception. 841 * 842 * <p>The existing exception will be embedded in the new 843 * one, but the new exception will have its own message.</p> 844 * 845 * @param message The detail message. 846 * @param e The exception to be wrapped in a SAXException. 847 *******************************************************************************/ 848 public this (immutable(char)[] message, Exception e) { 849 super (message, e); 850 } 851 852 /******************************************************************************* 853 * Return a detail message for this exception. 854 * 855 * <p>If there is an embedded exception, and if the SAXException 856 * has no detail message of its own, this method will return 857 * the detail message from the embedded exception.</p> 858 * 859 * @return The error or warning message. 860 *******************************************************************************/ 861 public immutable(char)[] message() { 862 if (msg is null && next !is null) { 863 return next.msg; 864 } 865 else { 866 return msg; 867 } 868 869 } 870 871 } 872 /******************************************************************************* 873 *******************************************************************************/ 874 class SaxParser(Ch = char) : XMLReader!(Ch), Locator!(Ch) { 875 876 private SaxHandler!(Ch) saxHandler; 877 private ErrorHandler!(Ch) errorHandler; 878 private EntityResolver!(Ch) entityResolver; 879 private const(Ch)[] content; 880 private Attribute!(Ch)[] attributes; 881 private int attrTop = 0; 882 private bool hasStartElement = false; 883 private const(Ch)[] startElemName; 884 private PullParser!(Ch) parser; 885 886 /******************************************************************************* 887 *******************************************************************************/ 888 public this() { 889 attributes = new Attribute!(Ch)[255]; 890 } 891 892 //////////////////////////////////////////////////////////////////// 893 // Configuration. 894 //////////////////////////////////////////////////////////////////// 895 /******************************************************************************* 896 * Look up the value of a feature flag. 897 * 898 * <p>The feature name is any fully-qualified URI. It is 899 * possible for an XMLReader to recognize a feature name but 900 * temporarily be unable to return its value. 901 * Some feature values may be available only in specific 902 * contexts, such as before, during, or after a parse. 903 * Also, some feature values may not be programmatically accessible. 904 * (In the case of an adapter for SAX1 {@link Parser}, there is no 905 * implementation-independent way to expose whether the underlying 906 * parser is performing validation, expanding external entities, 907 * and so forth.) </p> 908 * 909 * <p>All XMLReaders are required to recognize the 910 * http://xml.org/sax/features/namespaces and the 911 * http://xml.org/sax/features/namespace-prefixes feature names.</p> 912 * 913 * <p>Typical usage is something like this:</p> 914 * 915 * <pre> 916 * XMLReader r = new MySAXDriver(); 917 * 918 * // try to activate validation 919 * try { 920 * r.setFeature("http://xml.org/sax/features/validation", true); 921 * } catch (SAXException e) { 922 * System.err.println("Cannot activate validation."); 923 * } 924 * 925 * // register event handlers 926 * r.setContentHandler(new MyContentHandler()); 927 * r.setErrorHandler(new MyErrorHandler()); 928 * 929 * // parse the first document 930 * try { 931 * r.parse("http://www.foo.com/mydoc.xml"); 932 * } catch (IOException e) { 933 * System.err.println("I/O exception reading XML document"); 934 * } catch (SAXException e) { 935 * System.err.println("XML exception reading document."); 936 * } 937 * </pre> 938 * 939 * <p>Implementors are free (and encouraged) to invent their own features, 940 * using names built on their own URIs.</p> 941 * 942 * @param name The feature name, which is a fully-qualified URI. 943 * @return The current value of the feature (true or false). 944 * @exception org.xml.sax.SAXNotRecognizedException If the feature 945 * value can't be assigned or retrieved. 946 * @exception org.xml.sax.SAXNotSupportedException When the 947 * XMLReader recognizes the feature name but 948 * cannot determine its value at this time. 949 * @see #setFeature 950 *******************************************************************************/ 951 public bool getFeature(const(Ch)[] name) { 952 return false; 953 } 954 955 /******************************************************************************* 956 * Set the value of a feature flag. 957 * 958 * <p>The feature name is any fully-qualified URI. It is 959 * possible for an XMLReader to expose a feature value but 960 * to be unable to change the current value. 961 * Some feature values may be immutable or mutable only 962 * in specific contexts, such as before, during, or after 963 * a parse.</p> 964 * 965 * <p>All XMLReaders are required to support setting 966 * http://xml.org/sax/features/namespaces to true and 967 * http://xml.org/sax/features/namespace-prefixes to false.</p> 968 * 969 * @param name The feature name, which is a fully-qualified URI. 970 * @param value The requested value of the feature (true or false). 971 * @exception org.xml.sax.SAXNotRecognizedException If the feature 972 * value can't be assigned or retrieved. 973 * @exception org.xml.sax.SAXNotSupportedException When the 974 * XMLReader recognizes the feature name but 975 * cannot set the requested value. 976 * @see #getFeature 977 *******************************************************************************/ 978 public void setFeature(const(Ch)[] name, bool value) { 979 980 } 981 982 /******************************************************************************* 983 * Look up the value of a property. 984 * 985 * <p>The property name is any fully-qualified URI. It is 986 * possible for an XMLReader to recognize a property name but 987 * temporarily be unable to return its value. 988 * Some property values may be available only in specific 989 * contexts, such as before, during, or after a parse.</p> 990 * 991 * <p>XMLReaders are not required to recognize any specific 992 * property names, though an initial core set is documented for 993 * SAX2.</p> 994 * 995 * <p>Implementors are free (and encouraged) to invent their own properties, 996 * using names built on their own URIs.</p> 997 * 998 * @param name The property name, which is a fully-qualified URI. 999 * @return The current value of the property. 1000 * @exception org.xml.sax.SAXNotRecognizedException If the property 1001 * value can't be assigned or retrieved. 1002 * @exception org.xml.sax.SAXNotSupportedException When the 1003 * XMLReader recognizes the property name but 1004 * cannot determine its value at this time. 1005 * @see #setProperty 1006 *******************************************************************************/ 1007 public Object getProperty(const(Ch)[] name) { 1008 return null; 1009 } 1010 1011 /******************************************************************************* 1012 * Set the value of a property. 1013 * 1014 * <p>The property name is any fully-qualified URI. It is 1015 * possible for an XMLReader to recognize a property name but 1016 * to be unable to change the current value. 1017 * Some property values may be immutable or mutable only 1018 * in specific contexts, such as before, during, or after 1019 * a parse.</p> 1020 * 1021 * <p>XMLReaders are not required to recognize setting 1022 * any specific property names, though a core set is defined by 1023 * SAX2.</p> 1024 * 1025 * <p>This method is also the standard mechanism for setting 1026 * extended handlers.</p> 1027 * 1028 * @param name The property name, which is a fully-qualified URI. 1029 * @param value The requested value for the property. 1030 * @exception org.xml.sax.SAXNotRecognizedException If the property 1031 * value can't be assigned or retrieved. 1032 * @exception org.xml.sax.SAXNotSupportedException When the 1033 * XMLReader recognizes the property name but 1034 * cannot set the requested value. 1035 *******************************************************************************/ 1036 public void setProperty(const(Ch)[] name, Object value) { 1037 1038 } 1039 1040 //////////////////////////////////////////////////////////////////// 1041 // Event handlers. 1042 //////////////////////////////////////////////////////////////////// 1043 /******************************************************************************* 1044 * Allow an application to register an entity resolver. 1045 * 1046 * <p>If the application does not register an entity resolver, 1047 * the XMLReader will perform its own default resolution.</p> 1048 * 1049 * <p>Applications may register a new or different resolver in the 1050 * middle of a parse, and the SAX parser must begin using the new 1051 * resolver immediately.</p> 1052 * 1053 * @param resolver The entity resolver. 1054 * @see #getEntityResolver 1055 *******************************************************************************/ 1056 public void setEntityResolver(EntityResolver!(Ch) resolver) { 1057 entityResolver = resolver; 1058 } 1059 1060 /******************************************************************************* 1061 * Return the current entity resolver. 1062 * 1063 * @return The current entity resolver, or null if none 1064 * has been registered. 1065 * @see #setEntityResolver 1066 *******************************************************************************/ 1067 public EntityResolver!(Ch) getEntityResolver() { 1068 return entityResolver; 1069 } 1070 1071 /******************************************************************************* 1072 * Allow an application to register a content event handler. 1073 * 1074 * <p>If the application does not register a content handler, all 1075 * content events reported by the SAX parser will be silently 1076 * ignored.</p> 1077 * 1078 * <p>Applications may register a new or different handler in the 1079 * middle of a parse, and the SAX parser must begin using the new 1080 * handler immediately.</p> 1081 * 1082 * @param handler The content handler. 1083 * @see #getContentHandler 1084 *******************************************************************************/ 1085 public void setSaxHandler(SaxHandler!(Ch) handler) { 1086 saxHandler = handler; 1087 } 1088 1089 /******************************************************************************* 1090 * Return the current content handler. 1091 * 1092 * @return The current content handler, or null if none 1093 * has been registered. 1094 * @see #setContentHandler 1095 *******************************************************************************/ 1096 public SaxHandler!(Ch) getSaxHandler() { 1097 return saxHandler; 1098 } 1099 1100 /******************************************************************************* 1101 * Allow an application to register an error event handler. 1102 * 1103 * <p>If the application does not register an error handler, all 1104 * error events reported by the SAX parser will be silently 1105 * ignored; however, normal processing may not continue. It is 1106 * highly recommended that all SAX applications implement an 1107 * error handler to avoid unexpected bugs.</p> 1108 * 1109 * <p>Applications may register a new or different handler in the 1110 * middle of a parse, and the SAX parser must begin using the new 1111 * handler immediately.</p> 1112 * 1113 * @param handler The error handler. 1114 * @see #getErrorHandler 1115 *******************************************************************************/ 1116 public void setErrorHandler(ErrorHandler!(Ch) handler) { 1117 errorHandler = handler; 1118 } 1119 1120 /******************************************************************************* 1121 * Return the current error handler. 1122 * 1123 * @return The current error handler, or null if none 1124 * has been registered. 1125 * @see #setErrorHandler 1126 *******************************************************************************/ 1127 public ErrorHandler!(Ch) getErrorHandler() { 1128 return errorHandler; 1129 } 1130 1131 //////////////////////////////////////////////////////////////////// 1132 // Parsing. 1133 //////////////////////////////////////////////////////////////////// 1134 /******************************************************************************* 1135 * Parse an XML document. 1136 * 1137 * <p>The application can use this method to instruct the XML 1138 * reader to begin parsing an XML document from any valid input 1139 * source (a character stream, a byte stream, or a URI).</p> 1140 * 1141 * <p>Applications may not invoke this method while a parse is in 1142 * progress (they should create a new XMLReader instead for each 1143 * nested XML document). Once a parse is complete, an 1144 * application may reuse the same XMLReader object, possibly with a 1145 * different input source. 1146 * Configuration of the XMLReader object (such as handler bindings and 1147 * values established for feature flags and properties) is unchanged 1148 * by completion of a parse, unless the definition of that aspect of 1149 * the configuration explicitly specifies other behavior. 1150 * (For example, feature flags or properties exposing 1151 * characteristics of the document being parsed.) 1152 * </p> 1153 * 1154 * <p>During the parse, the XMLReader will provide information 1155 * about the XML document through the registered event 1156 * handlers.</p> 1157 * 1158 * <p>This method is synchronous: it will not return until parsing 1159 * has ended. If a client application wants to terminate 1160 * parsing early, it should throw an exception.</p> 1161 * 1162 * @param input The input source for the top-level of the 1163 * XML document. 1164 * @exception org.xml.sax.SAXException Any SAX exception, possibly 1165 * wrapping another exception. 1166 * @exception java.io.IOException An IO exception from the parser, 1167 * possibly from a byte stream or character stream 1168 * supplied by the application. 1169 * @see org.xml.sax.InputSource 1170 * @see #parse(java.lang.String) 1171 * @see #setEntityResolver 1172 * @see #setContentHandler 1173 * @see #setErrorHandler 1174 *******************************************************************************/ 1175 private void parse(InputStream input) { 1176 //TODO turn into a const(Ch)[] buffer 1177 doParse(); 1178 } 1179 1180 /******************************************************************************* 1181 * Parse an XML document from a system identifier (URI). 1182 * 1183 * <p>This method is a shortcut for the common case of reading a 1184 * document from a system identifier. It is the exact 1185 * equivalent of the following:</p> 1186 * 1187 * <pre> 1188 * parse(new InputSource(systemId)); 1189 * </pre> 1190 * 1191 * <p>If the system identifier is a URL, it must be fully resolved 1192 * by the application before it is passed to the parser.</p> 1193 * 1194 * @param systemId The system identifier (URI). 1195 * @exception org.xml.sax.SAXException Any SAX exception, possibly 1196 * wrapping another exception. 1197 * @exception java.io.IOException An IO exception from the parser, 1198 * possibly from a byte stream or character stream 1199 * supplied by the application. 1200 * @see #parse(org.xml.sax.InputSource) 1201 *******************************************************************************/ 1202 private void parseUrl(const(Ch)[] systemId) { 1203 //TODO turn url into a const(Ch)[] buffer 1204 doParse(); 1205 } 1206 1207 /******************************************************************************* 1208 * Parse an XML document from a character array. 1209 * 1210 * @param content The actual document content. 1211 * @exception org.xml.sax.SAXException Any SAX exception, possibly 1212 * wrapping another exception. 1213 * @exception java.io.IOException An IO exception from the parser, 1214 * possibly from a byte stream or character stream 1215 * supplied by the application. 1216 * @see #parse(org.xml.sax.InputSource) 1217 *******************************************************************************/ 1218 public void parse(const(Ch)[] content) { 1219 this.setContent(content); 1220 doParse(); 1221 } 1222 1223 /******************************************************************************* 1224 *******************************************************************************/ 1225 public void parse() { 1226 doParse(); 1227 } 1228 1229 /******************************************************************************* 1230 *******************************************************************************/ 1231 public void setContent(const(Ch)[] content) { 1232 if (!parser) { 1233 parser = new PullParser!(Ch)(content); 1234 } else { 1235 parser.reset(content); 1236 } 1237 } 1238 1239 /******************************************************************************* 1240 *******************************************************************************/ 1241 public void reset() { 1242 parser.reset(); 1243 } 1244 1245 /******************************************************************************* 1246 * The meat of the class. Turn the pull parser's nodes into SAX 1247 * events and send out to the SaxHandler. 1248 *******************************************************************************/ 1249 private void doParse() { 1250 saxHandler.setDocumentLocator(this); 1251 saxHandler.startDocument(); 1252 while (true) { 1253 switch (parser.next) { 1254 case XmlTokenType.StartElement : 1255 if (hasStartElement) { 1256 saxHandler.startElement(null, startElemName, null, attributes[0..attrTop]); 1257 hasStartElement = false; 1258 attrTop = 0; 1259 } 1260 startElemName = parser.localName; 1261 hasStartElement = true; 1262 break; 1263 case XmlTokenType.Attribute : 1264 attributes[attrTop].localName = parser.localName; 1265 attributes[attrTop].value = parser.rawValue; 1266 attrTop++; 1267 break; 1268 case XmlTokenType.EndElement : 1269 case XmlTokenType.EndEmptyElement : 1270 if (hasStartElement) { 1271 saxHandler.startElement(null, startElemName, null, attributes[0..attrTop]); 1272 hasStartElement = false; 1273 attrTop = 0; 1274 } 1275 saxHandler.endElement(null, parser.localName, null); 1276 break; 1277 case XmlTokenType.Data : 1278 if (hasStartElement) { 1279 saxHandler.startElement(null, startElemName, null, attributes[0..attrTop]); 1280 hasStartElement = false; 1281 attrTop = 0; 1282 } 1283 saxHandler.characters(parser.rawValue); 1284 break; 1285 case XmlTokenType.Comment : 1286 case XmlTokenType.CData : 1287 case XmlTokenType.Doctype : 1288 case XmlTokenType.PI : 1289 case XmlTokenType.None : 1290 if (hasStartElement) { 1291 saxHandler.startElement(null, startElemName, null, attributes[0..attrTop]); 1292 hasStartElement = false; 1293 attrTop = 0; 1294 } 1295 break; 1296 1297 case XmlTokenType.Done: 1298 goto foo; 1299 1300 default: 1301 throw new SAXException("unknown parser token type"); 1302 } 1303 } 1304 foo: 1305 saxHandler.endDocument(); 1306 } 1307 1308 /******************************************************************************* 1309 * Return the public identifier for the current document event. 1310 * 1311 * <p>The return value is the public identifier of the document 1312 * entity or of the external parsed entity in which the markup 1313 * triggering the event appears.</p> 1314 * 1315 * @return A string containing the public identifier, or 1316 * null if none is available. 1317 * @see #getSystemId 1318 *******************************************************************************/ 1319 public const(Ch)[] getPublicId() { 1320 return null; 1321 } 1322 1323 /******************************************************************************* 1324 * Return the system identifier for the current document event. 1325 * 1326 * <p>The return value is the system identifier of the document 1327 * entity or of the external parsed entity in which the markup 1328 * triggering the event appears.</p> 1329 * 1330 * <p>If the system identifier is a URL, the parser must resolve it 1331 * fully before passing it to the application. For example, a file 1332 * name must always be provided as a <em>file:...</em> URL, and other 1333 * kinds of relative URI are also resolved against their bases.</p> 1334 * 1335 * @return A string containing the system identifier, or null 1336 * if none is available. 1337 * @see #getPublicId 1338 *******************************************************************************/ 1339 public const(Ch)[] getSystemId() { 1340 return null; 1341 } 1342 1343 /******************************************************************************* 1344 * Return the line number where the current document event ends. 1345 * Lines are delimited by line ends, which are defined in 1346 * the XML specification. 1347 * 1348 * <p><strong>Warning:</strong> The return value from the method 1349 * is intended only as an approximation for the sake of diagnostics; 1350 * it is not intended to provide sufficient information 1351 * to edit the character content of the original XML document. 1352 * In some cases, these "line" numbers match what would be displayed 1353 * as columns, and in others they may not match the source text 1354 * due to internal entity expansion. </p> 1355 * 1356 * <p>The return value is an approximation of the line number 1357 * in the document entity or external parsed entity where the 1358 * markup triggering the event appears.</p> 1359 * 1360 * <p>If possible, the SAX driver should provide the line position 1361 * of the first character after the text associated with the document 1362 * event. The first line is line 1.</p> 1363 * 1364 * @return The line number, or -1 if none is available. 1365 * @see #getColumnNumber 1366 *******************************************************************************/ 1367 public int getLineNumber() { 1368 return 0; 1369 } 1370 1371 /******************************************************************************* 1372 * Return the column number where the current document event ends. 1373 * This is one-based number of Java <code>char</code> values since 1374 * the last line end. 1375 * 1376 * <p><strong>Warning:</strong> The return value from the method 1377 * is intended only as an approximation for the sake of diagnostics; 1378 * it is not intended to provide sufficient information 1379 * to edit the character content of the original XML document. 1380 * For example, when lines contain combining character sequences, wide 1381 * characters, surrogate pairs, or bi-directional text, the value may 1382 * not correspond to the column in a text editor's display. </p> 1383 * 1384 * <p>The return value is an approximation of the column number 1385 * in the document entity or external parsed entity where the 1386 * markup triggering the event appears.</p> 1387 * 1388 * <p>If possible, the SAX driver should provide the line position 1389 * of the first character after the text associated with the document 1390 * event. The first column in each line is column 1.</p> 1391 * 1392 * @return The column number, or -1 if none is available. 1393 * @see #getLineNumber 1394 *******************************************************************************/ 1395 public int getColumnNumber() { 1396 return 0; 1397 } 1398 1399 1400 } 1401 1402 1403 /******************************************************************************* 1404 * Interface for an XML filter. 1405 * 1406 * <p>An XML filter is like an XML reader, except that it obtains its 1407 * events from another XML reader rather than a primary source like 1408 * an XML document or database. Filters can modify a stream of 1409 * events as they pass on to the final application.</p> 1410 * 1411 * <p>The XMLFilterImpl helper class provides a convenient base 1412 * for creating SAX2 filters, by passing on all {@link org.xml.sax.EntityResolver 1413 * EntityResolver}, {@link org.xml.sax.DTDHandler DTDHandler}, 1414 * {@link org.xml.sax.ContentHandler ContentHandler} and {@link org.xml.sax.ErrorHandler 1415 * ErrorHandler} events automatically.</p> 1416 * 1417 * @since SAX 2.0 1418 * @author David Megginson 1419 * @version 2.0.1 (sax2r2) 1420 * @see org.xml.sax.helpers.XMLFilterImpl 1421 *******************************************************************************/ 1422 public abstract class XMLFilter(Ch = char) : XMLReader { 1423 1424 /******************************************************************************* 1425 * Set the parent reader. 1426 * 1427 * <p>This method allows the application to link the filter to 1428 * a parent reader (which may be another filter). The argument 1429 * may not be null.</p> 1430 * 1431 * @param parent The parent reader. 1432 *******************************************************************************/ 1433 public void setParent(XMLReader parent){ 1434 //do nothing 1435 } 1436 1437 /******************************************************************************* 1438 * Get the parent reader. 1439 * 1440 * <p>This method allows the application to query the parent 1441 * reader (which may be another filter). It is generally a 1442 * bad idea to perform any operations on the parent reader 1443 * directly: they should all pass through this filter.</p> 1444 * 1445 * @return The parent filter, or null if none has been set. 1446 *******************************************************************************/ 1447 public XMLReader getParent() { 1448 return null; 1449 } 1450 1451 } 1452 1453 /******************************************************************************* 1454 * Base class for deriving an XML filter. 1455 * 1456 * <p>This class is designed to sit between an {@link org.xml.sax.XMLReader 1457 * XMLReader} and the client application's event handlers. By default, it 1458 * does nothing but pass requests up to the reader and events 1459 * on to the handlers unmodified, but subclasses can override 1460 * specific methods to modify the event stream or the configuration 1461 * requests as they pass through.</p> 1462 * 1463 * @since SAX 2.0 1464 * @author David Megginson 1465 * @version 2.0.1 (sax2r2) 1466 * @see org.xml.sax.XMLFilter 1467 * @see org.xml.sax.XMLReader 1468 * @see org.xml.sax.EntityResolver 1469 * @see org.xml.sax.ContentHandler 1470 * @see org.xml.sax.ErrorHandler 1471 *******************************************************************************/ 1472 public class XMLFilterImpl(Ch = char) : SaxHandler, XMLFilter, EntityResolver, ErrorHandler { 1473 1474 //////////////////////////////////////////////////////////////////// 1475 // Constructors. 1476 //////////////////////////////////////////////////////////////////// 1477 /******************************************************************************* 1478 * Construct an empty XML filter, with no parent. 1479 * 1480 * <p>This filter will have no parent: you must assign a parent 1481 * before you start a parse or do any configuration with 1482 * setFeature or setProperty, unless you use this as a pure event 1483 * consumer rather than as an {@link XMLReader}.</p> 1484 * 1485 * @see org.xml.sax.XMLReader#setFeature 1486 * @see org.xml.sax.XMLReader#setProperty 1487 * @see #setParent 1488 *******************************************************************************/ 1489 public this () { 1490 1491 } 1492 1493 /******************************************************************************* 1494 * Construct an XML filter with the specified parent. 1495 * 1496 * @see #setParent 1497 * @see #getParent 1498 *******************************************************************************/ 1499 public this (XMLReader parent) { 1500 setParent(parent); 1501 } 1502 1503 //////////////////////////////////////////////////////////////////// 1504 // Implementation of org.xml.sax.XMLFilter. 1505 //////////////////////////////////////////////////////////////////// 1506 /******************************************************************************* 1507 * Set the parent reader. 1508 * 1509 * <p>This is the {@link org.xml.sax.XMLReader XMLReader} from which 1510 * this filter will obtain its events and to which it will pass its 1511 * configuration requests. The parent may itself be another filter.</p> 1512 * 1513 * <p>If there is no parent reader set, any attempt to parse 1514 * or to set or get a feature or property will fail.</p> 1515 * 1516 * @param parent The parent XML reader. 1517 * @see #getParent 1518 *******************************************************************************/ 1519 public void setParent(XMLReader parent) { 1520 this.parent = parent; 1521 } 1522 1523 /******************************************************************************* 1524 * Get the parent reader. 1525 * 1526 * @return The parent XML reader, or null if none is set. 1527 * @see #setParent 1528 *******************************************************************************/ 1529 public XMLReader getParent() { 1530 return parent; 1531 } 1532 1533 //////////////////////////////////////////////////////////////////// 1534 // Implementation of org.xml.sax.XMLReader. 1535 //////////////////////////////////////////////////////////////////// 1536 /******************************************************************************* 1537 * Set the value of a feature. 1538 * 1539 * <p>This will always fail if the parent is null.</p> 1540 * 1541 * @param name The feature name. 1542 * @param value The requested feature value. 1543 * @exception org.xml.sax.SAXNotRecognizedException If the feature 1544 * value can't be assigned or retrieved from the parent. 1545 * @exception org.xml.sax.SAXNotSupportedException When the 1546 * parent recognizes the feature name but 1547 * cannot set the requested value. 1548 *******************************************************************************/ 1549 public void setFeature(const(Ch)[] name, bool value) { 1550 if (parent !is null) { 1551 parent.setFeature(name, value); 1552 } 1553 else { 1554 throw new SAXException("Feature not recognized: " ~ name); 1555 } 1556 1557 } 1558 1559 /******************************************************************************* 1560 * Look up the value of a feature. 1561 * 1562 * <p>This will always fail if the parent is null.</p> 1563 * 1564 * @param name The feature name. 1565 * @return The current value of the feature. 1566 * @exception org.xml.sax.SAXNotRecognizedException If the feature 1567 * value can't be assigned or retrieved from the parent. 1568 * @exception org.xml.sax.SAXNotSupportedException When the 1569 * parent recognizes the feature name but 1570 * cannot determine its value at this time. 1571 *******************************************************************************/ 1572 public bool getFeature(const(Ch)[] name) { 1573 if (parent !is null) { 1574 return parent.getFeature(name); 1575 } 1576 else { 1577 throw new SAXException("Feature not recognized: " ~ name); 1578 } 1579 1580 } 1581 1582 /******************************************************************************* 1583 * Set the value of a property. 1584 * 1585 * <p>This will always fail if the parent is null.</p> 1586 * 1587 * @param name The property name. 1588 * @param value The requested property value. 1589 * @exception org.xml.sax.SAXNotRecognizedException If the property 1590 * value can't be assigned or retrieved from the parent. 1591 * @exception org.xml.sax.SAXNotSupportedException When the 1592 * parent recognizes the property name but 1593 * cannot set the requested value. 1594 *******************************************************************************/ 1595 public void setProperty(const(Ch)[] name, Object value) { 1596 if (parent !is null) { 1597 parent.setProperty(name, value); 1598 } 1599 else { 1600 throw new SAXException("Property not recognized: " ~ name); 1601 } 1602 1603 } 1604 1605 /******************************************************************************* 1606 * Look up the value of a property. 1607 * 1608 * @param name The property name. 1609 * @return The current value of the property. 1610 * @exception org.xml.sax.SAXNotRecognizedException If the property 1611 * value can't be assigned or retrieved from the parent. 1612 * @exception org.xml.sax.SAXNotSupportedException When the 1613 * parent recognizes the property name but 1614 * cannot determine its value at this time. 1615 *******************************************************************************/ 1616 public Object getProperty(const(Ch)[] name) { 1617 if (parent !is null) { 1618 return parent.getProperty(name); 1619 } 1620 else { 1621 throw new SAXException("Property not recognized: " ~ name); 1622 } 1623 1624 } 1625 1626 /******************************************************************************* 1627 * Set the entity resolver. 1628 * 1629 * @param resolver The new entity resolver. 1630 *******************************************************************************/ 1631 public void setEntityResolver(EntityResolver resolver) { 1632 entityResolver = resolver; 1633 } 1634 1635 /** 1636 * Get the current entity resolver. 1637 * 1638 * @return The current entity resolver, or null if none was set. 1639 *******************************************************************************/ 1640 public EntityResolver getEntityResolver() { 1641 return entityResolver; 1642 } 1643 1644 /******************************************************************************* 1645 * Set the content event handler. 1646 * 1647 * @param handler the new content handler 1648 *******************************************************************************/ 1649 public void setSaxHandler(SaxHandler handler) { 1650 saxHandler = handler; 1651 } 1652 1653 /******************************************************************************* 1654 * Get the content event handler. 1655 * 1656 * @return The current content handler, or null if none was set. 1657 *******************************************************************************/ 1658 public SaxHandler getSaxHandler() { 1659 return saxHandler; 1660 } 1661 1662 /******************************************************************************* 1663 * Set the error event handler. 1664 * 1665 * @param handler the new error handler 1666 *******************************************************************************/ 1667 public void setErrorHandler(ErrorHandler handler) { 1668 errorHandler = handler; 1669 } 1670 1671 /******************************************************************************* 1672 * Get the current error event handler. 1673 * 1674 * @return The current error handler, or null if none was set. 1675 *******************************************************************************/ 1676 public ErrorHandler getErrorHandler() { 1677 return errorHandler; 1678 } 1679 1680 /******************************************************************************* 1681 * Parse a document. 1682 * 1683 * @param input The input source for the document entity. 1684 * @exception org.xml.sax.SAXException Any SAX exception, possibly 1685 * wrapping another exception. 1686 * @exception java.io.IOException An IO exception from the parser, 1687 * possibly from a byte stream or character stream 1688 * supplied by the application. 1689 *******************************************************************************/ 1690 private void parse(InputStream input) { 1691 setupParse(); 1692 parent.parse(input); 1693 } 1694 1695 /******************************************************************************* 1696 * Parse the given content. 1697 * 1698 * @param input The input source for the document entity. 1699 * @exception org.xml.sax.SAXException Any SAX exception, possibly 1700 * wrapping another exception. 1701 * @exception java.io.IOException An IO exception from the parser, 1702 * possibly from a byte stream or character stream 1703 * supplied by the application. 1704 *******************************************************************************/ 1705 public void parse(const(Ch)[] content) { 1706 //TODO FIXME - create a buffer of this content as the input stream, and then parse. 1707 //setupParse(); 1708 //parent.parse(input); 1709 } 1710 1711 public void parse() {} 1712 public void setContent(const(Ch)[] content) {} 1713 1714 1715 /******************************************************************************* 1716 * Parse a document. 1717 * 1718 * @param systemId The system identifier as a fully-qualified URI. 1719 * @exception org.xml.sax.SAXException Any SAX exception, possibly 1720 * wrapping another exception. 1721 * @exception java.io.IOException An IO exception from the parser, 1722 * possibly from a byte stream or character stream 1723 * supplied by the application. 1724 *******************************************************************************/ 1725 private void parseUrl(const(Ch)[] systemId) { 1726 //TODO FIXME 1727 //parse(new InputSource(systemId)); 1728 } 1729 1730 //////////////////////////////////////////////////////////////////// 1731 // Implementation of org.xml.sax.EntityResolver. 1732 //////////////////////////////////////////////////////////////////// 1733 /******************************************************************************* 1734 * Filter an external entity resolution. 1735 * 1736 * @param publicId The entity's public identifier, or null. 1737 * @param systemId The entity's system identifier. 1738 * @return A new InputSource or null for the default. 1739 * @exception org.xml.sax.SAXException The client may throw 1740 * an exception during processing. 1741 * @exception java.io.IOException The client may throw an 1742 * I/O-related exception while obtaining the 1743 * new InputSource. 1744 *******************************************************************************/ 1745 public InputStream resolveEntity(const(Ch)[] publicId, const(Ch)[] systemId) { 1746 if (entityResolver !is null) { 1747 return entityResolver.resolveEntity(publicId, systemId); 1748 } 1749 else { 1750 return null; 1751 } 1752 1753 } 1754 1755 //////////////////////////////////////////////////////////////////// 1756 // Implementation of org.xml.sax.ContentHandler. 1757 //////////////////////////////////////////////////////////////////// 1758 /******************************************************************************* 1759 * Filter a new document locator event. 1760 * 1761 * @param locator The document locator. 1762 *******************************************************************************/ 1763 public void setDocumentLocator(Locator locator) { 1764 this.locator = locator; 1765 if (saxHandler !is null) { 1766 saxHandler.setDocumentLocator(locator); 1767 } 1768 1769 } 1770 1771 /******************************************************************************* 1772 * Filter a start document event. 1773 * 1774 * @exception org.xml.sax.SAXException The client may throw 1775 * an exception during processing. 1776 *******************************************************************************/ 1777 public void startDocument() { 1778 if (saxHandler !is null) { 1779 saxHandler.startDocument(); 1780 } 1781 1782 } 1783 1784 /******************************************************************************* 1785 * Filter an end document event. 1786 * 1787 * @exception org.xml.sax.SAXException The client may throw 1788 * an exception during processing. 1789 *******************************************************************************/ 1790 public void endDocument() { 1791 if (saxHandler !is null) { 1792 saxHandler.endDocument(); 1793 } 1794 1795 } 1796 1797 /******************************************************************************* 1798 * Filter a start Namespace prefix mapping event. 1799 * 1800 * @param prefix The Namespace prefix. 1801 * @param uri The Namespace URI. 1802 * @exception org.xml.sax.SAXException The client may throw 1803 * an exception during processing. 1804 *******************************************************************************/ 1805 public void startPrefixMapping(const(Ch)[] prefix, const(Ch)[] uri) { 1806 if (saxHandler !is null) { 1807 saxHandler.startPrefixMapping(prefix, uri); 1808 } 1809 1810 } 1811 1812 /******************************************************************************* 1813 * Filter an end Namespace prefix mapping event. 1814 * 1815 * @param prefix The Namespace prefix. 1816 * @exception org.xml.sax.SAXException The client may throw 1817 * an exception during processing. 1818 *******************************************************************************/ 1819 public void endPrefixMapping(const(Ch)[] prefix) { 1820 if (saxHandler !is null) { 1821 saxHandler.endPrefixMapping(prefix); 1822 } 1823 1824 } 1825 1826 /******************************************************************************* 1827 * Filter a start element event. 1828 * 1829 * @param uri The element's Namespace URI, or the empty string. 1830 * @param localName The element's local name, or the empty string. 1831 * @param qName The element's qualified (prefixed) name, or the empty 1832 * string. 1833 * @param atts The element's attributes. 1834 * @exception org.xml.sax.SAXException The client may throw 1835 * an exception during processing. 1836 *******************************************************************************/ 1837 public void startElement(const(Ch)[] uri, const(Ch)[] localName, const(Ch)[] qName, Attribute[] atts) { 1838 if (saxHandler !is null) { 1839 saxHandler.startElement(uri, localName, qName, atts); 1840 } 1841 1842 } 1843 1844 /******************************************************************************* 1845 * Filter an end element event. 1846 * 1847 * @param uri The element's Namespace URI, or the empty string. 1848 * @param localName The element's local name, or the empty string. 1849 * @param qName The element's qualified (prefixed) name, or the empty 1850 * string. 1851 * @exception org.xml.sax.SAXException The client may throw 1852 * an exception during processing. 1853 *******************************************************************************/ 1854 public void endElement(const(Ch)[] uri, const(Ch)[] localName, const(Ch)[] qName) { 1855 if (saxHandler !is null) { 1856 saxHandler.endElement(uri, localName, qName); 1857 } 1858 1859 } 1860 1861 /******************************************************************************* 1862 * Filter a character data event. 1863 * 1864 * @param ch An array of characters. 1865 * @exception org.xml.sax.SAXException The client may throw 1866 * an exception during processing. 1867 *******************************************************************************/ 1868 public void characters(Ch[] ch) { 1869 if (saxHandler !is null) { 1870 saxHandler.characters(ch); 1871 } 1872 1873 } 1874 1875 /******************************************************************************* 1876 * Filter an ignorable whitespace event. 1877 * 1878 * @param ch An array of characters. 1879 * @param start The starting position in the array. 1880 * @param length The number of characters to use from the array. 1881 * @exception org.xml.sax.SAXException The client may throw 1882 * an exception during processing. 1883 *******************************************************************************/ 1884 public void ignorableWhitespace(Ch[] ch) { 1885 if (saxHandler !is null) { 1886 saxHandler.ignorableWhitespace(ch); 1887 } 1888 1889 } 1890 1891 /******************************************************************************* 1892 * Filter a processing instruction event. 1893 * 1894 * @param target The processing instruction target. 1895 * @param data The text following the target. 1896 * @exception org.xml.sax.SAXException The client may throw 1897 * an exception during processing. 1898 *******************************************************************************/ 1899 public void processingInstruction(const(Ch)[] target, const(Ch)[] data) { 1900 if (saxHandler !is null) { 1901 saxHandler.processingInstruction(target, data); 1902 } 1903 1904 } 1905 1906 /******************************************************************************* 1907 * Filter a skipped entity event. 1908 * 1909 * @param name The name of the skipped entity. 1910 * @exception org.xml.sax.SAXException The client may throw 1911 * an exception during processing. 1912 *******************************************************************************/ 1913 public void skippedEntity(const(Ch)[] name) { 1914 if (saxHandler !is null) { 1915 saxHandler.skippedEntity(name); 1916 } 1917 1918 } 1919 1920 //////////////////////////////////////////////////////////////////// 1921 // Implementation of org.xml.sax.ErrorHandler. 1922 //////////////////////////////////////////////////////////////////// 1923 /******************************************************************************* 1924 * Filter a warning event. 1925 * 1926 * @param e The warning as an exception. 1927 * @exception org.xml.sax.SAXException The client may throw 1928 * an exception during processing. 1929 *******************************************************************************/ 1930 public void warning(SAXException e) { 1931 if (errorHandler !is null) { 1932 errorHandler.warning(e); 1933 } 1934 1935 } 1936 1937 /******************************************************************************* 1938 * Filter an error event. 1939 * 1940 * @param e The error as an exception. 1941 * @exception org.xml.sax.SAXException The client may throw 1942 * an exception during processing. 1943 *******************************************************************************/ 1944 public void error(SAXException e) { 1945 if (errorHandler !is null) { 1946 errorHandler.error(e); 1947 } 1948 1949 } 1950 1951 /******************************************************************************* 1952 * Filter a fatal error event. 1953 * 1954 * @param e The error as an exception. 1955 * @exception org.xml.sax.SAXException The client may throw 1956 * an exception during processing. 1957 *******************************************************************************/ 1958 public void fatalError(SAXException e) { 1959 if (errorHandler !is null) { 1960 errorHandler.fatalError(e); 1961 } 1962 1963 } 1964 1965 //////////////////////////////////////////////////////////////////// 1966 // Internal methods. 1967 //////////////////////////////////////////////////////////////////// 1968 /******************************************************************************* 1969 * Set up before a parse. 1970 * 1971 * <p>Before every parse, check whether the parent is 1972 * non-null, and re-register the filter for all of the 1973 * events.</p> 1974 *******************************************************************************/ 1975 private void setupParse() { 1976 if (parent is null) { 1977 throw new Exception("No parent for filter"); 1978 } 1979 parent.setEntityResolver(this); 1980 parent.setSaxHandler(this); 1981 parent.setErrorHandler(this); 1982 } 1983 1984 //////////////////////////////////////////////////////////////////// 1985 // Internal state. 1986 //////////////////////////////////////////////////////////////////// 1987 private XMLReader parent = null; 1988 1989 private Locator locator = null; 1990 1991 private EntityResolver entityResolver = null; 1992 1993 private SaxHandler saxHandler = null; 1994 1995 private ErrorHandler errorHandler = null; 1996 1997 } 1998 1999 2000 2001 /******************************************************************************* 2002 * Interface for reading an XML document using callbacks. 2003 * 2004 * <p>XMLReader is the interface that an XML parser's SAX2 driver must 2005 * implement. This interface allows an application to set and 2006 * query features and properties in the parser, to register 2007 * event handlers for document processing, and to initiate 2008 * a document parse.</p> 2009 * 2010 * <p>All SAX interfaces are assumed to be synchronous: the 2011 * {@link #parse parse} methods must not return until parsing 2012 * is complete, and readers must wait for an event-handler callback 2013 * to return before reporting the next event.</p> 2014 * 2015 * <p>This interface replaces the (now deprecated) SAX 1.0 {@link 2016 * org.xml.sax.Parser Parser} interface. The XMLReader interface 2017 * contains two important enhancements over the old Parser 2018 * interface (as well as some minor ones):</p> 2019 * 2020 * <ol> 2021 * <li>it adds a standard way to query and set features and 2022 * properties; and</li> 2023 * <li>it adds Namespace support, which is required for many 2024 * higher-level XML standards.</li> 2025 * </ol> 2026 * 2027 * <p>There are adapters available to convert a SAX1 Parser to 2028 * a SAX2 XMLReader and vice-versa.</p> 2029 * 2030 * @since SAX 2.0 2031 * @author David Megginson 2032 * @version 2.0.1+ (sax2r3pre1) 2033 * @see org.xml.sax.XMLFilter 2034 * @see org.xml.sax.helpers.ParserAdapter 2035 * @see org.xml.sax.helpers.XMLReaderAdapter 2036 *******************************************************************************/ 2037 public interface XMLReader(Ch = char) { 2038 2039 //////////////////////////////////////////////////////////////////// 2040 // Configuration. 2041 //////////////////////////////////////////////////////////////////// 2042 /******************************************************************************* 2043 * Look up the value of a feature flag. 2044 * 2045 * <p>The feature name is any fully-qualified URI. It is 2046 * possible for an XMLReader to recognize a feature name but 2047 * temporarily be unable to return its value. 2048 * Some feature values may be available only in specific 2049 * contexts, such as before, during, or after a parse. 2050 * Also, some feature values may not be programmatically accessible. 2051 * (In the case of an adapter for SAX1 {@link Parser}, there is no 2052 * implementation-independent way to expose whether the underlying 2053 * parser is performing validation, expanding external entities, 2054 * and so forth.) </p> 2055 * 2056 * <p>All XMLReaders are required to recognize the 2057 * http://xml.org/sax/features/namespaces and the 2058 * http://xml.org/sax/features/namespace-prefixes feature names.</p> 2059 * 2060 * <p>Typical usage is something like this:</p> 2061 * 2062 * <pre> 2063 * XMLReader r = new MySAXDriver(); 2064 * 2065 * // try to activate validation 2066 * try { 2067 * r.setFeature("http://xml.org/sax/features/validation", true); 2068 * } catch (SAXException e) { 2069 * System.err.println("Cannot activate validation."); 2070 * } 2071 * 2072 * // register event handlers 2073 * r.setContentHandler(new MyContentHandler()); 2074 * r.setErrorHandler(new MyErrorHandler()); 2075 * 2076 * // parse the first document 2077 * try { 2078 * r.parse("http://www.foo.com/mydoc.xml"); 2079 * } catch (IOException e) { 2080 * System.err.println("I/O exception reading XML document"); 2081 * } catch (SAXException e) { 2082 * System.err.println("XML exception reading document."); 2083 * } 2084 * </pre> 2085 * 2086 * <p>Implementors are free (and encouraged) to invent their own features, 2087 * using names built on their own URIs.</p> 2088 * 2089 * @param name The feature name, which is a fully-qualified URI. 2090 * @return The current value of the feature (true or false). 2091 * @exception org.xml.sax.SAXNotRecognizedException If the feature 2092 * value can't be assigned or retrieved. 2093 * @exception org.xml.sax.SAXNotSupportedException When the 2094 * XMLReader recognizes the feature name but 2095 * cannot determine its value at this time. 2096 * @see #setFeature 2097 *******************************************************************************/ 2098 public bool getFeature(const(Ch)[] name); 2099 2100 /******************************************************************************* 2101 * Set the value of a feature flag. 2102 * 2103 * <p>The feature name is any fully-qualified URI. It is 2104 * possible for an XMLReader to expose a feature value but 2105 * to be unable to change the current value. 2106 * Some feature values may be immutable or mutable only 2107 * in specific contexts, such as before, during, or after 2108 * a parse.</p> 2109 * 2110 * <p>All XMLReaders are required to support setting 2111 * http://xml.org/sax/features/namespaces to true and 2112 * http://xml.org/sax/features/namespace-prefixes to false.</p> 2113 * 2114 * @param name The feature name, which is a fully-qualified URI. 2115 * @param value The requested value of the feature (true or false). 2116 * @exception org.xml.sax.SAXNotRecognizedException If the feature 2117 * value can't be assigned or retrieved. 2118 * @exception org.xml.sax.SAXNotSupportedException When the 2119 * XMLReader recognizes the feature name but 2120 * cannot set the requested value. 2121 * @see #getFeature 2122 *******************************************************************************/ 2123 public void setFeature(const(Ch)[] name, bool value); 2124 2125 /******************************************************************************* 2126 * Look up the value of a property. 2127 * 2128 * <p>The property name is any fully-qualified URI. It is 2129 * possible for an XMLReader to recognize a property name but 2130 * temporarily be unable to return its value. 2131 * Some property values may be available only in specific 2132 * contexts, such as before, during, or after a parse.</p> 2133 * 2134 * <p>XMLReaders are not required to recognize any specific 2135 * property names, though an initial core set is documented for 2136 * SAX2.</p> 2137 * 2138 * <p>Implementors are free (and encouraged) to invent their own properties, 2139 * using names built on their own URIs.</p> 2140 * 2141 * @param name The property name, which is a fully-qualified URI. 2142 * @return The current value of the property. 2143 * @exception org.xml.sax.SAXNotRecognizedException If the property 2144 * value can't be assigned or retrieved. 2145 * @exception org.xml.sax.SAXNotSupportedException When the 2146 * XMLReader recognizes the property name but 2147 * cannot determine its value at this time. 2148 * @see #setProperty 2149 *******************************************************************************/ 2150 public Object getProperty(const(Ch)[] name); 2151 2152 /******************************************************************************* 2153 * Set the value of a property. 2154 * 2155 * <p>The property name is any fully-qualified URI. It is 2156 * possible for an XMLReader to recognize a property name but 2157 * to be unable to change the current value. 2158 * Some property values may be immutable or mutable only 2159 * in specific contexts, such as before, during, or after 2160 * a parse.</p> 2161 * 2162 * <p>XMLReaders are not required to recognize setting 2163 * any specific property names, though a core set is defined by 2164 * SAX2.</p> 2165 * 2166 * <p>This method is also the standard mechanism for setting 2167 * extended handlers.</p> 2168 * 2169 * @param name The property name, which is a fully-qualified URI. 2170 * @param value The requested value for the property. 2171 * @exception org.xml.sax.SAXNotRecognizedException If the property 2172 * value can't be assigned or retrieved. 2173 * @exception org.xml.sax.SAXNotSupportedException When the 2174 * XMLReader recognizes the property name but 2175 * cannot set the requested value. 2176 *******************************************************************************/ 2177 public void setProperty(const(Ch)[] name, Object value); 2178 2179 //////////////////////////////////////////////////////////////////// 2180 // Event handlers. 2181 //////////////////////////////////////////////////////////////////// 2182 /******************************************************************************* 2183 * Allow an application to register an entity resolver. 2184 * 2185 * <p>If the application does not register an entity resolver, 2186 * the XMLReader will perform its own default resolution.</p> 2187 * 2188 * <p>Applications may register a new or different resolver in the 2189 * middle of a parse, and the SAX parser must begin using the new 2190 * resolver immediately.</p> 2191 * 2192 * @param resolver The entity resolver. 2193 * @see #getEntityResolver 2194 *******************************************************************************/ 2195 public void setEntityResolver(EntityResolver!(Ch) resolver); 2196 2197 /******************************************************************************* 2198 * Return the current entity resolver. 2199 * 2200 * @return The current entity resolver, or null if none 2201 * has been registered. 2202 * @see #setEntityResolver 2203 *******************************************************************************/ 2204 public EntityResolver!(Ch) getEntityResolver(); 2205 2206 /******************************************************************************* 2207 * Allow an application to register a content event handler. 2208 * 2209 * <p>If the application does not register a content handler, all 2210 * content events reported by the SAX parser will be silently 2211 * ignored.</p> 2212 * 2213 * <p>Applications may register a new or different handler in the 2214 * middle of a parse, and the SAX parser must begin using the new 2215 * handler immediately.</p> 2216 * 2217 * @param handler The content handler. 2218 * @see #getContentHandler 2219 *******************************************************************************/ 2220 public void setSaxHandler(SaxHandler!(Ch) handler); 2221 2222 /******************************************************************************* 2223 * Return the current content handler. 2224 * 2225 * @return The current content handler, or null if none 2226 * has been registered. 2227 * @see #setContentHandler 2228 *******************************************************************************/ 2229 public SaxHandler!(Ch) getSaxHandler(); 2230 2231 /******************************************************************************* 2232 * Allow an application to register an error event handler. 2233 * 2234 * <p>If the application does not register an error handler, all 2235 * error events reported by the SAX parser will be silently 2236 * ignored; however, normal processing may not continue. It is 2237 * highly recommended that all SAX applications implement an 2238 * error handler to avoid unexpected bugs.</p> 2239 * 2240 * <p>Applications may register a new or different handler in the 2241 * middle of a parse, and the SAX parser must begin using the new 2242 * handler immediately.</p> 2243 * 2244 * @param handler The error handler. 2245 * @see #getErrorHandler 2246 *******************************************************************************/ 2247 public void setErrorHandler(ErrorHandler!(Ch) handler); 2248 2249 /******************************************************************************* 2250 * Return the current error handler. 2251 * 2252 * @return The current error handler, or null if none 2253 * has been registered. 2254 * @see #setErrorHandler 2255 *******************************************************************************/ 2256 public ErrorHandler!(Ch) getErrorHandler(); 2257 2258 //////////////////////////////////////////////////////////////////// 2259 // Parsing. 2260 //////////////////////////////////////////////////////////////////// 2261 /******************************************************************************* 2262 * Parse an XML document. 2263 * 2264 * <p>The application can use this method to instruct the XML 2265 * reader to begin parsing an XML document from any valid input 2266 * source (a character stream, a byte stream, or a URI).</p> 2267 * 2268 * <p>Applications may not invoke this method while a parse is in 2269 * progress (they should create a new XMLReader instead for each 2270 * nested XML document). Once a parse is complete, an 2271 * application may reuse the same XMLReader object, possibly with a 2272 * different input source. 2273 * Configuration of the XMLReader object (such as handler bindings and 2274 * values established for feature flags and properties) is unchanged 2275 * by completion of a parse, unless the definition of that aspect of 2276 * the configuration explicitly specifies other behavior. 2277 * (For example, feature flags or properties exposing 2278 * characteristics of the document being parsed.) 2279 * </p> 2280 * 2281 * <p>During the parse, the XMLReader will provide information 2282 * about the XML document through the registered event 2283 * handlers.</p> 2284 * 2285 * <p>This method is synchronous: it will not return until parsing 2286 * has ended. If a client application wants to terminate 2287 * parsing early, it should throw an exception.</p> 2288 * 2289 * @param input The input source for the top-level of the 2290 * XML document. 2291 * @exception org.xml.sax.SAXException Any SAX exception, possibly 2292 * wrapping another exception. 2293 * @exception java.io.IOException An IO exception from the parser, 2294 * possibly from a byte stream or character stream 2295 * supplied by the application. 2296 * @see org.xml.sax.InputSource 2297 * @see #parse(java.lang.String) 2298 * @see #setEntityResolver 2299 * @see #setContentHandler 2300 * @see #setErrorHandler 2301 *******************************************************************************/ 2302 private void parse(InputStream input); 2303 2304 /******************************************************************************* 2305 * Parse an XML document from a system identifier (URI). 2306 * 2307 * <p>This method is a shortcut for the common case of reading a 2308 * document from a system identifier. It is the exact 2309 * equivalent of the following:</p> 2310 * 2311 * <pre> 2312 * parse(new InputSource(systemId)); 2313 * </pre> 2314 * 2315 * <p>If the system identifier is a URL, it must be fully resolved 2316 * by the application before it is passed to the parser.</p> 2317 * 2318 * @param systemId The system identifier (URI). 2319 * @exception org.xml.sax.SAXException Any SAX exception, possibly 2320 * wrapping another exception. 2321 * @exception java.io.IOException An IO exception from the parser, 2322 * possibly from a byte stream or character stream 2323 * supplied by the application. 2324 * @see #parse(org.xml.sax.InputSource) 2325 *******************************************************************************/ 2326 private void parseUrl(const(Ch)[] systemId); 2327 2328 /******************************************************************************* 2329 * Parse an XML document from a character array. 2330 * 2331 * @param content The actual document content. 2332 * @exception org.xml.sax.SAXException Any SAX exception, possibly 2333 * wrapping another exception. 2334 * @exception java.io.IOException An IO exception from the parser, 2335 * possibly from a byte stream or character stream 2336 * supplied by the application. 2337 * @see #parse(org.xml.sax.InputSource) 2338 *******************************************************************************/ 2339 public void parse(const(Ch)[] content); 2340 2341 /******************************************************************************* 2342 *******************************************************************************/ 2343 public void parse(); 2344 2345 /******************************************************************************* 2346 *******************************************************************************/ 2347 public void setContent(const(Ch)[] content); 2348 2349 }