6 XML Programming Best Practices

This chapter describes the best programming practices to use when creating Java applications that process XML data.

This chapter includes the following sections:

When to Use the DOM, SAX, and StAX APIs

You can parse an XML document with the DOM, SAX, or StAX APIs. This section describes when to use each API.

Use DOM when the application needs random access, repeated traversal, or in-memory modification and representative documents fit within the application’s measured memory and latency budget. Benchmark with production-size documents and expected concurrency; there is no portable element-count cutoff.

SAX: Use SAX for single-pass, event-driven processing when the application is structured around parser callbacks and does not need an in-memory tree. Document depth and repeated element names are not selection limits; the handler must maintain whatever context the application requires.

StAX: Use StAX for single-pass streaming when application code should control when the parser advances. The cursor API offers low-overhead pull processing; the event API offers event objects and iterator-style composition. Like SAX, StAX can keep memory use low, but it is a distinct pull model rather than an API based on SAX.

Increasing Performance of XML Validation

Validation has a runtime cost, so enable it according to the document contract and trust boundary. When a protocol or application requires conformance, validate the complete document. For DTD validation, call SAXParserFactory.setValidating(true) or DocumentBuilderFactory.setValidating(true). For XML Schema validation, create a Schema and set it on the parser factory with setSchema(Schema).

If full DTD or XML Schema validation is not required, check the specific business invariants the application depends on and describe those checks as business-rule validation, not XML validity. Business-rule checks do not establish DTD or XML Schema conformance.

Measure representative workloads before changing validation strategy. Configure external-access controls separately; enabling validation does not authorize unrestricted retrieval of schemas or DTDs.

When to Use XML Schemas or DTDs

There are two ways to describe the structure of an XML document: DTDs and XML Schemas.

Schemas are much more expressive than DTDs because the set of available data types to describe XML elements is much richer and you can describe more specifically what is valid in an XML document. A SOAP message must not contain a Document Type Declaration. Use XML Schema to describe and, where required, validate application payload structures. Because SOAP is the main messaging protocol used in Web services, consider using Schemas to describe any XML documents that might be used as either input or output parameters to Web services.

Still, DTDs have a few advantages. Because DTDs are less expressive than Schemas, they are easier to write and manage.

However, Oracle recommends that you use Schemas to describe your XML documents.

Configuring External Entity Resolution for Maximum Performance

Oracle highly recommends you store external entities locally whenever possible rather than always retrieving the entity over the network. Storage improves the performance of your applications because it is much faster to look up an entity on the same machine as WebLogic Server than it is to look it up over a network connection.

For detailed information on configuring external entity resolution for WebLogic Server, see External Entity Configuration Tasks.

Enable external resolution only when the application requires a known external resource. Map approved public/system identifiers to trusted local registry entries. Configure the calling parser's resolver and external-access policy to fail closed for unknown identifiers; do not assume that the registry mapping alone rejects an identifier that has no mapping. For untrusted XML that does not require DTDs or external entities, disable those features and external access. Do not allow a missing registry entry to fall back to an unrestricted network fetch.

Using SAX InputSources

When you use the SAX API to parse an XML document, you first create an InputSource object from the XML document and then pass the InputSource object to the parse() method. You can create the InputSource object from either a java.io.InputStream or java.io.Reader object based on your XML data.

Oracle recommends that you create an InputSource from a java.io.InputStream object whenever possible. When passed an InputStream object, the SAX parser auto-detects the character encoding of the XML data and automatically instantiates an InputStreamReader object for you, using the correct character encoding. In other words, the parser does all the character encoding work for you, which is more likely to be error-free at runtime than if you decide to specify the character encoding yourself.

Improving Performance of Transformations

XSLT is a language for transforming an XML document into a different format, such as another XML document, HTML, WML, and so on. To use XSLT, you create a stylesheet that defines how each element in the input XML document should be transformed in the output document.

Although XSLT is a powerful language, creating stylesheets for complex transformations can be very complicated. In addition, the actual transformation requires a lot of resources and might decrease the performance of your application.

Measure representative transformations before changing implementation. For repeated XSLT, compile the stylesheet once with TransformerFactory.newTemplates(Source), reuse the thread-safe Templates object, and create a separate Transformer for each operation or thread. Configure the factory to restrict external DTD and stylesheet access for untrusted inputs. Choose DOM only when the transformation requires random access or mutation and its measured memory cost is acceptable; use streaming sources/results where the stylesheet and processor allow them.