and the Java Coffee Cup logo are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and ...... Fe
JSR 206 Java API for XML Processing (JAXP) 1.3
Jeff Suttor Norman Walsh Kohsuke Kawaguchi
JSR 206 Java™ API for XML Processing (JAXP) 1.3 by Jeff Suttor, Norman Walsh, and Kohsuke Kawaguchi Copyright © 2004 Sun Microsystems, Inc.
Final 1.0.0 The JSR 206 Java™ API for XML Processing (JAXP) 1.3 Expert Group would like to thank participants in the Java Community that are reviewing this Java Specification Request. All comments, feedback and guidance from the Java Community is appreciated. Please submit comments to .
Specification: JSR-206: Java™ API for XML Processing (JAXP) 1.3 Specification ("Specification"), Status: Final Release, Release: September 1, 2004 Copyright 2004 Sun Microsystems, Inc. 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved.
NOTICE; LIMITED LICENSE GRANTS Sun Microsystems, Inc. ("Sun") hereby grants you a fully-paid, non-exclusive, non-transferable, worldwide, limited license (without the right to sublicense), under the Sun’s applicable intellectual property rights to view, download, use and reproduce the Specification only for the purpose of internal evaluation, which shall be understood to include developing applications intended to run on an implementation of the Specification provided that such applications do not themselves implement any portion(s) of the Specification. Sun also grants you a perpetual, non-exclusive, worldwide, fully paid-up, royalty free, limited license (without the right to sublicense) under any applicable copyrights or patent rights it may have in the Specification to create and/or distribute an Independent Implementation of the Specification that: (i) fully implements the Spec(s) including all its required interfaces and functionality; (ii) does not modify, subset, superset or otherwise extend the Licensor Name Space, or include any public or protected packages, classes, Java interfaces, fields or methods within the Licensor Name Space other than those required/authorized by the Specification or Specifications being implemented; and (iii) passes the TCK (including satisfying the requirements of the applicable TCK Users Guide) for such Specification. The foregoing license is expressly conditioned on your not acting outside its scope. No license is granted hereunder for any other purpose. You need not include limitations (i)-(iii) from the previous paragraph or any other particular "pass through" requirements in any license You grant concerning the use of your Independent Implementation or products derived from it. However, except with respect to implementations of the Spe cification (and products derived from them) that satisfy limitations (i)-(iii) from the previous paragraph, You may neither: (a) grant or otherwise pass through to your licensees any licenses under Sun’s applicable intellectual property rights; nor (b) authorize your licensees to make any claims concerning their implementation’s compliance with the Spec in question. For the purposes of this Agreement: "Independent Implementation" shall mean an implementation of the Specification that neither derives from any of Sun’s source code or binary code materials nor, except with an appropriate and separate license from Sun, includes any of Sun’s source code or binary code materials; and "Licensor Name Space" shall mean the public class or interface declarations whose names begin with "java", "javax", "com.sun" or their equivalents in any subsequent naming convention adopted by Sun through the Java Community Process, or any recognized successors or replacements thereof. This Agreement will terminate immediately without notice from Sun if you fail to comply with any material provision of or act outside the scope of the licenses granted above.
TRADEMARKS No right, title, or interest in or to any trademarks, service marks, or trade names of Sun, Sun’s licensors, Specification Lead or the Specification Lead’s licensors is granted hereunder. Sun, Sun Microsystems, the Sun logo, Java, J2SE, J2EE, J2ME, Java Compatible, the Java Compatible Logo, and the Java Coffee Cup logo are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
DISCLAIMER OF WARRANTIES THE SPECIFICATION IS PROVIDED "AS IS". SUN MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT, THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE OR THAT ANY PRACTICE
Final 1.0.0
OR IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADE SECRETS OR OTHER RIGHTS. This document does not represent any commitment to release or implement any portion of the Specification in any product. THE SPECIFICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFIC ATION, IF ANY. SUN MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME. Any use of such changes in the Specification will be governed by the then-current license for the ap plicable version of the Specification.
LIMITATION OF LIABILITY TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, IN CLUDING WITHOUT LIMITATION, LOST REVENUE, PROFITS OR ’ that are inside of tags. While HTML specifies what each tag and attribute means, as well as their presentation attributes in a browser, XML uses tags only to delimit pieces of /> Templates templates = tfactory.newTemplates(new DOMSource(docBuilder.parse(xslID), xslID)); // Get a transformer from the templates. Transformer transformer = templates.newTransformer(); // Set up to resolve URLs that correspond to our foo2.xml, to
11
Final 1.0.0
Plugability Layer
// a DOM node. Use an anonymous class for the URI resolver. // Be sure to return the same DOM tree every time for the given URI. final Node xmlSubdir1Foo2Node = docBuilder.parse("xml/subdir1/foo2.xml"); transformer.setURIResolver(new URIResolver() { public Source resolve(String href, String base) throws TransformerException { // ignore base because we’re lazy, or we don’t care. return (href.equals("subdir1/foo2.xml")) ? new DOMSource(xmlSubdir1Foo2Node) : null; } } ); // Now the transformer will call our anonymous URI resolver // when it encounters the document("subdir1/foo2.xml") invocation. transformer.transform(new DOMSource(docBuilder.parse(sourceID), sourceID), }
new StreamResul
The following example performs a transformation using DOM nodes as input for the TransformerFactory, as input for the Transformer, and as the output of the transformation:
TransformerFactory tfactory = TransformerFactory.newInstance(); // Make sure the TransformerFactory supports the DOM feature. if (tfactory.getFeature(DOMSource.FEATURE) && tfactory.getFeature(DOMResult.FEATURE)) { // Use javax.xml.parsers to create our DOMs. DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance(); dfactory.setNamespaceAware(true); // do this always for XSLT DocumentBuilder docBuilder = dfactory.newDocumentBuilder(); // Create the Templates from a DOM. Node xslDOM = docBuilder.parse(xslID); DOMSource dsource = new DOMSource(xslDOM, xslID); Templates templates = tfactory.newTemplates(dsource); // Create the source tree in the form of a DOM. Node sourceNode = docBuilder.parse(sourceID); // Create a DOMResult that the transformation will fill in. DOMResult dresult = new DOMResult(); // And transform from the source DOM tree to a result DOM tree. Transformer transformer = templates.newTransformer(); transformer.transform(new DOMSource(sourceNode, sourceID), dresult); // The root of the result tree may now be obtained from // the DOMResult object. Node out = dresult.getNode(); // Serialize it to System.out for diagnostics. Transformer serializer = tfactory.newTransformer(); serializer.transform(new DOMSource(out), new StreamResult(System.out)); } The following code fragment illustrates the use of the SAXSource and SAXResult objects:
12
Final 1.0.0
Plugability Layer
TransformerFactory tfactory = TransformerFactory.newInstance(); // Does this factory support SAX features? if (tfactory.getFeature(SAXSource.FEATURE) && tfactory.getFeature(SAXResult.FEATURE)) { // Get a transformer. Transformer transformer = tfactory.newTransformer(new StreamSource(xslID)); // Create a reader for reading. XMLReader reader = XMLReaderFactory.createXMLReader(); transformer.transform(new SAXSource(reader, new InputSource(sourceID)), new SAXResult(new E } The following illustrates the feeding of SAX events from an org.xml.sax.XMLReader to a Transformer:
TransformerFactory tfactory = TransformerFactory.newInstance(); // Does this factory support SAX features? if (tfactory.getFeature(SAXTransformerFactory.FEATURE)) { // If so, we can safely cast. SAXTransformerFactory stfactory = ((SAXTransformerFactory) tfactory); // A TransformerHandler is a ContentHandler that will listen for // SAX events, and transform them to the result. TransformerHandler handler = stfactory.newTransformerHandler(new StreamSource(xslID)); // Set the result handling to be a serialization to System.out. handler.setResult(new StreamResult(System.out)); handler.getTransformer().setParameter("a-param", "hello to you!"); // Create a reader, and set it’s content handler to be the TransformerHandler. XMLReader reader = XMLReaderFactory.createXMLReader(); reader.setContentHandler(handler); // It’s a good idea for the parser to send lexical events. // The TransformerHandler is also a LexicalHandler. reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler); // Parse the source XML, and send the parse events to the TransformerHandler. reader.parse(sourceID); } The following code fragment illustrates the creation of a Templates object from SAX2 events sent from an XMLReader:
TransformerFactory tfactory = TransformerFactory.newInstance(); // Does this factory support SAX features? if (tfactory.getFeature(SAXTransformerFactory.FEATURE)) { // If so, we can safely cast. SAXTransformerFactory stfactory = ((SAXTransformerFactory) tfactory); // Have the factory create a special ContentHandler that will // create a Templates object. TemplatesHandler handler = stfactory.newTemplatesHandler(); // If you don’t do this, the TemplatesHandler won’t know how to // resolve relative URLs. handler.setSystemId(xslID);
13
Final 1.0.0
Plugability Layer
// Create a reader, and set it’s content handler to be the TemplatesHandler. XMLReader reader = XMLReaderFactory.createXMLReader(); reader.setContentHandler(handler); // Parse the source XML, and send the parse events to the TemplatesHandler. reader.parse(xslID); // Get the Templates reference from the handler. Templates templates = handler.getTemplates(); // Ready to transform. Transformer transformer = templates.newTransformer(); transformer.transform(new StreamSource(sourceID), new StreamResult(System.out)); } The following illustrates several transformations chained together. Each filter points to a parent org.xml.sax.XMLReader ,and the final transformation is caused by invoking org.xml.sax.XMLRead er#parse on the final reader in the chain:
TransformerFactory tfactory = TransformerFactory.newInstance(); // Does this factory support SAX features? if (tfactory.getFeature(SAXTransformerFactory.FEATURE)) { Templates stylesheet1 = tfactory.newTemplates(new StreamSource(xslID_1)); Transformer transformer1 = stylesheet1.newTransformer(); SAXTransformerFactory stf = (SAXTransformerFactory)tfactory; XMLReader reader = XMLReaderFactory.createXMLReader(); XMLFilter filter1 = stf.newXMLFilter(new StreamSource(xslID_1)); XMLFilter filter2 = stf.newXMLFilter(new StreamSource(xslID_2)); XMLFilter filter3 = stf.newXMLFilter(new StreamSource(xslID_3)); // transformer1 will use a SAX parser as it’s reader. filter1.setParent(reader); // transformer2 will use transformer1 as it’s reader. filter2.setParent(filter1); // transform3 will use transform2 as it’s reader. filter3.setParent(filter2); filter3.setContentHandler(new ExampleContentHandler()); // filter3.setContentHandler(new org.xml.sax.helpers.DefaultHandler()); // // // // // //
Now, when you call transformer3 to parse, it will set itself as the ContentHandler for transform2, and call transform2.parse, which will set itself as the content handler for transform1, and call transform1.parse, which will set itself as the content listener for the SAX parser, and call parser.parse(new InputSource("xml/foo.xml")).
filter3.parse(new InputSource(sourceID)); } The following code fragment illustrates the use of the stream Source and Result objects:
14
Final 1.0.0
Plugability Layer
// Create a TransformerFactory instance. TransformerFactory tfactory = TransformerFactory.newInstance(); InputStream xslIS = new BufferedInputStream(new FileInputStream(xslID)); StreamSource xslSource = new StreamSource(xslIS); // Note that if we don’t do this, relative URLs cannot be resolved correctly! xslSource.setSystemId(xslID); // Create a transformer for the stylesheet. Transformer transformer = tfactory.newTransformer(xslSource); InputStream xmlIS = new BufferedInputStream(new FileInputStream(sourceID)); StreamSource xmlSource = new StreamSource(xmlIS); // Note that if we don’t do this, relative URLs cannot be resolved correctly! xmlSource.setSystemId(sourceID); // Transform the source XML to System.out. transformer.transform( xmlSource, new StreamResult(System.out)); An example of how one could pass the System property as a command line option is: java -Djavax.xml.transform.TransformerFactory=org.apache.xalan.processor.TransformerFactoryImpl user.parserApp
XPath Plugability The XPath Plugability classes allow an application programmer to obtain an XPath object that is based on a specific object model implementation. In order to obtain an XPath object, a programmer first obtains an instance of the XPathFactory. The XPathFactory instance is obtained via the static newInstance method of the XPathFactory class. This method uses the following ordered lookup procedure to determine the XPathFactory implementation class to load: •
Use the javax.xml.xpath.XPathFactory system property
•
Use the properties file "lib/jaxp.properties" in the JRE directory. This configuration file is in standard java.util.Properties format and contains the fully qualified name of the implementation class with the key being the system property defined above. The jaxp.properties file is read only once by the JSR 206 Java™ API for XML Processing (JAXP) 1.3 implementation and it’s values are then cached for future use. If the file does not exist when the first attempt is made to read from it, no further attempts are made to check for its existence. It is not possible to change the value of any property in jaxp.properties after it has been read for the first time.
•
Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for the classname in the file META-INF/services/javax.xml.xpath.XPathFactory in jars available to the runtime.
•
Platform default XPathFactory131 instance.
If the XPathFactory131 implementation class cannot be loaded or instantiated at runtime, a XPathFactoryCon figurationError is thrown. This error message should contain a descriptive explanation of the problem and how the user can resolve it.
15
Final 1.0.0
Plugability Layer
Examples The following example loads a document and evaluates the XPath expression “/widgets/wid get[@name='a']/@quantity” against it.
// parse the XML as a W3C Document DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); org.w3c.Document document = builder.parse(new File("/widgets.xml")); // evaluate the XPath expression against the Document XPath xpath = XPathFactory.newInstance().newXPath(); String expression = "/widgets/widget[@name='a']/@quantity"; Double quantity = (Double) xpath.evaluate(expression, document, XPathConstants.NUMBER); The evaluation of XPath expressions can return their results as one of five types: Node, NodeList, Boolean, Double, and String. The third argument to evaluate selects the result type. To get the quantity attribute as a string, use:
String str_quantity = (String) xpath.evaluate(expression, document, XPathConstants.STRING); This may seem somewhat clumsy, but it is necessary because the he result type is not a property of the expression, it is a property of the context in which it is evaluated.
Validation Plugability The Validation Plugability classes allow an application programmer to obtain a Schema156 Object that is based on a specific schema language implementation. In order to obtain a Schema156 Object, a programmer first obtains an instance of the SchemaFactory157. The SchemaFactory157 instance is obtained via the static newInstance method of the SchemaFactory157 Class. This method uses the following ordered lookup procedure to determine the SchemaFactory157 implementation Class to load: •
If the system property javax.xml.validation.SchemaFactory:schemaLanguage is present (where schemaLanguage is the parameter to newInstance), then its value is read as a Class name. The method will try to create a new instance of this Class by using the ClassLoader, and returns it if it is successfully created.
•
Read the properties file $java.home/lib/jaxp.properties in the JRE directory. This configuration file is in standard java.util.Properties format. $java.home/lib/jaxp.properties is read only once by the JSR 206 Java™ API for XML Processing (JAXP) 1.3 implementation and it’s values are then cached for future use. If the file does not exist when the first attempt is made to read from it, no further attempts are made to check for its existence. It is not possible to change the value of any property in $java.home/lib/jaxp.properties after it has been read for the first time. If the property javax.xml.validation.SchemaFactory:schemaLanguage is present (where schemaLanguage is the parameter to newInstance), then its value is read as a Class name. The method will try to create a new instance of this Class by using the ClassLoader, and returns it if it is successfully created.
16
Final 1.0.0
Plugability Layer
•
The ClassLoader is asked for service provider provider-configuration files matching javax.xml.valida tion.SchemaFactory in the resource directory META-INF/services. See the JAR File Specification for file format and parsing rules. Each potential service provider is required to implement the method:
isSchemaLanguageSupported(String schemaLanguage) The first service provider found in ClassLoader order that supports the specified schema language is returned. •
A platform default SchemaFactory157 is located in an implementation specific way. There must be a platform default SchemaFactory157 for W3C®,(World Wide Web Consortium) XML Schema.
If all lookups fail, then an IllegalArgumentException will be thrown.
Tip See Properties.load(java.io.InputStream) for exactly how a property file is parsed. In partic ular, colons ’:’ need to be escaped in a property file, so make sure schema language URIs are properly escaped. For example:
http\://www.w3.org/2001/XMLSchema=org.acme.XSSchemaFactory
Thread Safety Implementations of the SAXParser38, DocumentBuilder25, Transformer62, Validator172 and Validat orHandler180 abstract classes are not expected to be thread safe by this specification. This means that application programmers should not expect to be able to use the same instance of a SAXParser38, DocumentBuilder25, Transformer62, Validator172 or ValidatorHandler180 in more than one thread at a time without side effects. If a programmer is creating a multi-threaded application, they should make sure that only one thread has access to any given SAXParser38, DocumentBuilder25, Transformer62, Validator172 or ValidatorHandler180 instance. Configuration of a SAXParserFactory47, DocumentBuilderFactory30 TransformerFactory68 or SchemaFactory157 is also not expected to be thread safe. This means that an application programmer should not allow a SAXParserFactory47, DocumentBuilderFactory30, TransformerFactory68 or SchemaFact ory157 instance to have its setter methods accessed from more than one thread. It is expected that the newSAXParser50 method of a SAXParserFactory47 implementation, the newDocument Builder33 method of a DocumentBuilderFactory30 and the newTransformer method of a Transformer Factory68 will be thread safe without side effects. This means that an application programmer should expect to be able to create parser instances in multiple threads at once from a shared factory without side effects or problems. Note that Schema156 is thread safe.
Properties For Enabling Schema Validation javax.xml.parsers.SAXParserFactory The validating property must have the value true for any of the property strings defined below to take effect. Otherwise, the values of the properties defined below will be ignored. This value can be set by invoking
17
Final 1.0.0
Plugability Layer
setValidating(true) javax.xml.parsers.SAXParser The setProperty method in SAXParser must support the property strings defined below to indicate the schema language and the source of the schema file(s) to the parser: http://java.sun.com/xml/jaxp/properties/schemaLanguage This property defines the schema language to be used for validation. The value of this property must be the URI of the schema language specification. To be compliant with this version of the specification, the implementation must support the W3C XML Schema [http://www.w3.org/2001/XMLSchema] specification. When setValidating is set to true and a schema language is set, then the parser must validate against that schema language only. For example if an application sets the schemaLanguage property to XML Schemas then the parser must try to validate against the XML schema only, even if the document has a DOCTYPE declaration that refers to a DTD. http://java.sun.com/xml/jaxp/properties/schemaSource The XML Schema Recommendation explicitly states that the inclusion of schemaLocation / noNamespaceSchema Location attributes in an instance document is only a hint; it does not mandate that these attributes must be used to locate schemas. The schemaSource property lets the user set the schema(s) to validate against. If the target namespace of a schema specified using this property matches the target namespace of a schema occurring in schemaLocation attribute, the schema specified by the user using this property will be used and the instance document’s schemaLocation attribute will be effectively ignored. However if the target namespace of any schema specified using this property doesn’t match the target namespace of a schema occurring in the instance document, then the hint specified in the instance document will be used for validation. The acceptable value for this property must be one of the following: •
URI of the schema as a String
•
InputStream with the contents of the schema
•
SAX InputSource
•
File
•
an array of Objects with the contents being one of the types defined above. An array of Objects can be used only when the schema language has the ability to assemble a schema at runtime. When an array of Objects is passed it is illegal to have two schemas that share the same namespace.
If no target namespace is defined, then only one schema can be referenced by the property and it must work exactly the way xsi:noNamespaceSchemaLocation does. It is illegal to set the schemaSource property if the schemaLanguage property has not been set. In that case, the imple mentation must throw a SAXNotSupportedException with a detailed message. If the schemaSource property is set using a String, the parser must pass the value of the property to the org.xml.sax.EntityResolver with the publicId set to null. javax.xml.parsers.DocumentBuilderFactory The same property strings as described above for the SAXParser must be supported by DocumentBuilderFact ory.setAttribute method.
18
Final 1.0.0
Plugability Layer
When setValidating is set to true and a schema language is set then the parser must validate against that schema language only. For example if an application sets the schema language property to XML Schemas the parser must try to validate against the XML schema only, even if the document has a DOCTYPE declaration that refers to a DTD. It is illegal to set the schemaSource property if the schemaLanguage property has not been set. In that case, the imple mentation must throw an IllegalArgumentException with a detailed message. Note: None of the properties will take effect till the setValidating(true) has been called on the SAXParserFactory or the DocumentBuilderFactory that was used to create the SAXParser or the DocumentBuilder. The table below shows the results of various configuration scenarios. In all cases, we assume that setValidating(true) has been called. Document has schema language schema source schema location Document Valid Schema file used DOCTYPE? property set to property set? attribute present ated against XML Schemas? in document? no
no
no
no
error as per JAXP N/A 1.1 spec. Must have a DOCTYPE declaration when validation is turned on.
no
no
no
yes
Error. Schema lan N/A guage must be set.
no
no
yes
yes / no
Error schema lan N/A guage must be set.
yes / no
yes
no
yes
xml schemas
schema files re ferred to using the schema location attributes present in the instance document
yes / no
yes
yes
no
xml schemas
schema file re ferred to in the schemaSource property
yes / no
yes
yes
yes
xml schemas
schema file re ferred to in the schema source property, if the tar get namespace matches. The schema file re ferred to in the schema location attribute is ignored only if the target namespace matches
yes
no
no
yes / no
DTD
DTD referred to in the DOCTYPE
19
Final 1.0.0
Plugability Layer
Document has schema language schema source schema location Document Valid Schema file used DOCTYPE? property set to property set? attribute present ated against XML Schemas? in document? yes
no
yes
yes / no
Error. Schema N/A source cannot be set without setting the schema lan guage.
Samples Using the Properties Sax parser sample:
try { SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); spf.setValidating(true); SAXParser sp = spf.newSAXParser(); sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", "http://www.example. DefaultHandler dh = new DefaultHandler(); sp.parse("http://www.wombats.com/foo.xml", dh); } catch(SAXException se) { se.printStackTrace(); } DOM parser sample:
try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); dbf.setValidating(true); dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", "http://www.example.com/Report.xsd"); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse("http://www.wombats.com/foo.xml"); } catch(DOMException de) { de.printStackTrace(); }
Recommended Implementation of Properties It is recommended that parser implementations recognize properties defined in the form of a URI, as above. Such im plementations avoid conflicts in the use of the feature and property strings among parser implementations. That is also the way in which SAX defines feature and property strings.
20
Final 1.0.0
Chapter 4. Conformance Requirements This section describes the conformance requirements for implementations of this specification. Implementations that are accessed via the APIs defined here must implement these constraints, without exception, to provide a predictable environment for application development and deployment. Note that applications may provide non-conformant implementations that are able to support the plugability mechanism defined in the specification, however the system default processor must meet the conformance requirements defined below.
All Implementations of JSR 206 Java™ API for XML Processing (JAXP) 1.3 Must Support the Following Specifications: •
Extensible Markup Language (XML) 1.1 [http://www.w3.org/TR/xml11], Extensible Markup Language (XML) 1.0 (Second Edition) [http://www.w3.org/TR/REC-xml], Extensible Markup Language (XML) 1.0 (Second Edition) Errata [http://www.w3.org/XML/xml-V10-2e-errata]
•
Namespaces in XML 1.1 [http://www.w3.org/TR/xml-names11/], Namespaces in [spec.namespaces-1.0.link;], Namespaces in XML 1.0 Errata [spec.namespaces-1.0-errata.link;]
•
XML Schema Part 1: Structures [http://www.w3.org/TR/xmlschema-1/], XML Schema Part 1: Structures Errata [http://www.w3.org/2001/05/xmlschema-errata#Errata1], XML Schema Part 2: />, then the Qualified Name would be "{http://xyz.foo.com/yada/baz.html}foo". Note that the prefix is lost.
Result Tree Serialization Serialization of the result tree to a stream can be controlled with the javax.xml.transform.Transformer.setOutputProp erties [ Method setOutputProperties(java.util.Properties)] and the javax.xml.transform.Transformer.setOutputProperty [ Method setOutputProperty(java.lang.String, java.lang.String)] methods. These properties only apply to stream results, they have no effect when the result is a DOM tree or SAX event stream. Strings that match the XSLT specification for xsl:output attributes [http://www.w3.org/TR/xslt#output] can be referenced from the javax.xml.transform.OutputKeys [ Class OutputKeys] class. Other strings can be specified as well. If the transformer does not recognize an output key, a java.lang.IllegalArgumentException is thrown, unless the key name is namespace qualified [#qname-delimiter]. Output key names that are namespace qualified are always allowed, although they may be ignored by some implementations. If all that is desired is the simple identity transformation of a source to a result, then javax.xml.transform.Transformer Factory [ Class TransformerFactory] provides a javax.xml.transform.TransformerFactory.newTransformer [ Method newTransformer()] method with no arguments. This method creates a Transformer that effectively copies the source to the result. This method may be used to create a DOM from SAX events or to create an XML or HTML stream from a DOM or SAX events.
Exceptions and Error Reporting The transformation API throw three types of specialized exceptions. A javax.xml.transform.TransformerFactoryCon figurationError [ Error TransformerFactoryConfigurationError] is parallel to the javax.xml.parsers.FactoryConfigura tionError, and is thrown when a configuration problem with the TransformerFactory exists. This error will typically be thrown when the transformation factory class specified with the "javax.xml.transform.TransformerFactory" system property cannot be found or instantiated. A javax.xml.transform.TransformerConfigurationException [ Exception TransformerConfigurationException] may be thrown if for any reason a Transformer can not be created. A TransformerConfigurationException may be thrown if there is a syntax error in the transformation instructions, for example when javax.xml.transform.TransformerFact ory.newTransformer [ Method newTransformer(javax.xml.transform.Source)] is called. javax.xml.transform.TransformerException [ Exception TransformerException] is a general exception that occurs during the course of a transformation. A transformer exception may wrap another exception, and if any of the javax.xml.transform.TransformerException.printStackTrace [ Method printStackTrace()] methods are called on it, it will produce a list of stack dumps, starting from the most recent. The transformer exception also provides a javax.xml.transform.SourceLocator [ Interface SourceLocator] object which indicates where in the source tree or transformation instructions the error occurred. javax.xml.transform.TransformerException.getMessageAndLocation [ Method getMessageAndLocation()] may be called to get an error message with location info, and javax.xml.trans form.TransformerException.getLocationAsString [ Method getLocationAsString()] may be called to get just the location string. Transformation warnings and errors are sent to an javax.xml.transform.ErrorListener [ Interface ErrorListener], at which point the application may decide to report the error or warning, and may decide to throw an Exception for a non-fatal error. The ErrorListener may be set via javax.xml.transform.TransformerFactory.setErrorListener [ Method setErrorListener(javax.xml.transform.ErrorListener)] for reporting errors that have to do with syntax errors in
58
Final 1.0.0
Package javax.xml.transform
the transformation instructions, or via javax.xml.transform.Transformer.setErrorListener [ Method setErrorListen er(javax.xml.transform.ErrorListener)] to report errors that occur during the transformation. The ErrorListener on both objects will always be valid and non- null, whether set by the application or a default implementation provided by the processor. The default implementation provided by the processor will report all warnings and errors to Sys tem.err and does not throw any Exceptions. Applications are strongly encouraged to register and use ErrorL isteners that insure proper behavior for warnings and errors.
Resolution of URIs within a transformation The API provides a way for URIs referenced from within the stylesheet instructions or within the transformation to be resolved by the calling application. This can be done by creating a class that implements the javax.xml.transform.URI Resolver [ Interface URIResolver] interface, with its one method, javax.xml.transform.URIResolver.resolve [ Method resolve(java.lang.String, java.lang.String)], and use this class to set the URI resolution for the transformation instructions or transformation with javax.xml.transform.TransformerFactory.setURIResolver [ Method setURIResolv er(javax.xml.transform.URIResolver)] or javax.xml.transform.Transformer.setURIResolver [ Method setURIResolv er(javax.xml.transform.URIResolver)]. The URIResolver.resolve method takes two String arguments, the URI found in the stylesheet instructions or built as part of the transformation process, and the base URI against which the first argument will be made absolute if the absolute URI is required. The returned javax.xml.transform.Source [ Interface Source] object must be usable by the transformer, as specified in its implemented features.
Class OutputKeys Provides string constants that can be used to set output properties for a Transformer, or to retrieve output properties from a Transformer or Templates object. All the fields in this class are read-only.
Synopsis public OutputKeys { } See Also
section 16 of the XSL Transformations [http://www.w3.org/TR/xslt#output]
(XSLT)
W3C
Recommendation
(XSLT)
W3C
Recommendation.
Inheritance Path java.lang.Object | javax.xml.transform.OutputKeys
Members Field C/>, then the qualified name would be "{http://xyz.foo.com/yada/baz.html}foo". Note that no prefix is used. An IllegalArgumentException is thrown if any of the argument keys are not recognized and are not namespace qualified.
Method setOutputProperty(String, String) public void abstract setOutputProperty(java.lang.String name, java.lang.String value) throws java.lang.IllegalArgumentException;
Parameters name
A non-null String that specifies an output property name, which may be namespace qualified.
value
The non-null string value of the output property.
Exceptions IllegalArgumentException See Also
If the property is not supported, and is not qualified with a namespace.
javax.xml.transform.OutputKeys [Class OutputKeys]
Set an output property that will be in effect for the transformation. Pass a qualified property name as a two-part string, the namespace URI enclosed in curly braces ({}), followed by the local name. If the name has a null URL, the String only contain the local name. An application can safely check for a non-null URI by testing to see if the first character of the name is a '{' character. For example, if a URI and local name were obtained from an element defined with , then the qualified name would be "{http://xyz.foo.com/yada/baz.html}foo". Note that no prefix is used.
66
Final 1.0.0
Package javax.xml.transform
The Properties object that was passed to javax.xml.transform.Transformer.setOutputProperties [ Method setOutput Properties(java.util.Properties)] won't be effected by calling this method.
Method setParameter(String, Object) public void abstract setParameter(java.lang.String name, java.lang.Object value);
Parameters name
The name of the parameter, which may begin with a namespace URI in curly braces ({}).
value
The value object. This can be any valid Java object. It is up to the processor to provide the proper object coersion or to simply pass the object on for use in an extension.
Exceptions NullPointerException
If value is null.
Add a parameter for the transformation. Pass a qualified name as a two-part string, the namespace URI enclosed in curly braces ({}), followed by the local name. If the name has a null URL, the String only contain the local name. An application can safely check for a nonnull URI by testing to see if the first character of the name is a '{' character. For example, if a URI and local name were obtained from an element defined with , then the qualified name would be "{http://xyz.foo.com/yada/baz.html}foo". Note that no prefix is used.
Method setURIResolver(URIResolver) public void abstract setURIResolver(javax.xml.transform.URIResolver resolver);
Parameters resolver
An object that implements the URIResolver interface, or null.
Set an object that will be used to resolve URIs used in document(). If the resolver argument is null, the URIResolver value will be cleared and the transformer will no longer have a resolver.
Method transform(Source, Result) public void abstract transform(javax.xml.transform.Source xmlSource, javax.xml.transform.Result outputTarget) throws TransformerException;
Parameters xmlSource
The XML input to transform.
outputTarget
The Result of transforming the xmlSource.
67
Final 1.0.0
Package javax.xml.transform
Exceptions TransformerException
If an unrecoverable error occurs during the course of the transformation.
Transform the XML Source to a Result. Specific transformation behavior is determined by the settings of the TransformerFactory68 in effect when the Transformer62 was instantiated and any modifications made to the Transformer62 instance. An empty Source is represented as an empty document as constructed by javax.xml.parsers.DocumentBuilder#new Document(). The result of transforming an empty Source depends on the transformation behavior; it is not always an empty Result.
Class TransformerFactory A TransformerFactory instance can be used to create javax.xml.transform.Transformer [ Class Transformer] and javax.xml.transform.Templates [ Interface Templates] objects. The system property that determines which Factory implementation to create is named "javax.xml.trans form.TransformerFactory". This property names a concrete subclass of the TransformerFactory68 abstract class. If the property is not defined, a platform default is be used.
Synopsis public TransformerFactory { protected TransformerFactory(); static TransformerFactory newInstance() throws TransformerFactoryConfigurationError; public Transformer abstract newTransformer(javax.xml.transform.Source source) throws TransformerConfigurationException; public Transformer abstract newTransformer() throws TransformerConfigurationException; public Templates abstract newTemplates(javax.xml.transform.Source source) throws TransformerConfigurationException; public Source abstract getAssociatedStylesheet(javax.xml.transform.Source source, java.lang.String media, java.lang.String title, java.lang.String charset) throws TransformerConfigurationException; public void abstract setURIResolver(javax.xml.transform.URIResolver resolver); public URIResolver abstract getURIResolver(); public void abstract setFeature(java.lang.String name, boolean value) throws TransformerConfigurationException; public boolean abstract getFeature(java.lang.String name);
68
Final 1.0.0
Package javax.xml.transform
public void abstract setAttribute(java.lang.String name, java.lang.Object value); public Object abstract getAttribute(java.lang.String name); public void abstract setErrorListener(javax.xml.transform.ErrorListener listener); public ErrorListener abstract getErrorListener(); } Author
Jeff Suttor [mailto:
[email protected]]
Inheritance Path java.lang.Object | javax.xml.transform.TransformerFactory
Members Constructor TransformerFactory() protected TransformerFactory(); Default constructor is protected on purpose.
Method getAssociatedStylesheet(Source, String, String, String) public Source abstract getAssociatedStylesheet(javax.xml.transform.Source source, java.lang.String media, java.lang.String title, java.lang.String charset) throws TransformerConfigurationException;
Parameters source
The XML source document.
media
The media attribute to be matched. May be null, in which case the prefered templates will be used (i.e. alternate = no).
title
The value of the title attribute to match. May be null.
charset
The value of the charset attribute to match. May be null.
returns
A Source Object suitable for passing to the TransformerFactory68.
Exceptions TransformerConfigura tionException See Also
An Exception is thrown if an error occurings during parsing of the source.
Associating Style Sheets with XML documents Version 1.0 [http://www.w3.org/TR/xml-stylesheet/]
69
Final 1.0.0
Package javax.xml.transform
Get the stylesheet specification(s) associated with the XML Source document via the xml-stylesheet processing in struction [http://www.w3.org/TR/xml-stylesheet/] that match the given criteria. Note that it is possible to return several stylesheets, in which case they are applied as if they were a list of imports or cascades in a single stylesheet.
Method getAttribute(String) public Object abstract getAttribute(java.lang.String name);
Parameters name
The name of the attribute.
returns
value The value of the attribute.
Allows the user to retrieve specific attributes on the underlying implementation. An IllegalArgumentException is thrown if the underlying implementation doesn't recognize the attribute.
Method getErrorListener() public ErrorListener abstract getErrorListener(); Get the error event handler for the TransformerFactory.
Method getFeature(String) public boolean abstract getFeature(java.lang.String name);
Parameters name
Feature name.
returns
The current state of the feature, true or false.
Exceptions NullPointerException
If the name parameter is null.
Look up the value of a feature. Feature names are fully qualified java.net.URIs. Implementations may define their own features. false is returned if this TransformerFactory68 or the Transformer62s or Templates it creates cannot support the feature. It is possible for an TransformerFactory68 to expose a feature value but be unable to change its state.
Method getURIResolver() public URIResolver abstract getURIResolver(); Get the object that is used by default during the transformation to resolve URIs used in document(), xsl:import, or xsl:include.
Method newInstance() static TransformerFactory newInstance() throws TransformerFactoryConfigurationError;
70
Final 1.0.0
Package javax.xml.transform
Exceptions TransformerFactoryCon figurationError
Thrown if the implementation is not available or cannot be instantiated.
Obtain a new instance of a TransformerFactory68. This static method creates a new factory instance This method uses the following ordered lookup procedure to determine the TransformerFactory68 implementation class to load: •
Use the javax.xml.transform.TransformerFactory system property.
•
Use the properties file "lib/jaxp.properties" in the JRE directory. This configuration file is in standard java.util.Properties format and contains the fully qualified name of the implementation class with the key being the system property defined above. The jaxp.properties file is read only once by the JAXP implementation and it's values are then cached for future use. If the file does not exist when the first attempt is made to read from it, no further attempts are made to check for its existence. It is not possible to change the value of any property in jaxp.properties after it has been read for the first time.
•
Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for a classname in the file META-INF/services/javax.xml.transform.Transformer Factory in jars available to the runtime.
•
Platform default TransformerFactory68 instance.
Once an application has obtained a reference to a TransformerFactory it can use the factory to configure and obtain parser instances.
Method newTemplates(Source) public Templates abstract newTemplates(javax.xml.transform.Source source) throws TransformerConfigurationException;
Parameters source
An object that holds a URL, input stream, etc.
returns
A Templates object capable of being used for transformation purposes, never null.
Exceptions TransformerConfigura tionException
May throw this during the parse when it is constructing the Templates object and fails.
Process the Source into a Templates object, which is a a compiled representation of the source. This Templates object may then be used concurrently across multiple threads. Creating a Templates object allows the TransformerFactory to do detailed performance optimization of transformation instructions, without penalizing runtime transformation.
Method newTransformer() public Transformer abstract newTransformer() throws TransformerConfigurationException;
71
Final 1.0.0
Package javax.xml.transform
Exceptions TransformerConfigura tionException
Thrown if it is not possible to create a Transformer62 instance.
Create a new Transformer that performs a copy of the Source to the Result. i.e. the "identity transform".
Method newTransformer(Source) public Transformer abstract newTransformer(javax.xml.transform.Source source) throws TransformerConfigurationException;
Parameters source
Source of XSLT document used to create Transformer62. Examples of XML Sources include DOMSource [ Class DOMSource], SAXSource [ Class SAXSource], and StreamSource [ Class StreamSource].
returns
A Transformer62 object that may be used to perform a transformation in a single Thread, never null.
Exceptions TransformerConfigura tionException See Also
Thrown if there are errors when parsing the Source or it is not possible to create a Transformer62 instance.
XSL Transformations (XSLT) Version 1.0 [http://www.w3.org/TR/xslt]
Process the Source into a Transformer62 Object. The Source is an XSLT document that conforms to XSL Transformations (XSLT) Version 1.0 [http://www.w3.org/TR/xslt]. Care must be taken not to use this Transformer 62 in multiple Threads running concurrently. Different TransformerFactories can be used concurrently by different Threads.
Method setAttribute(String, Object) public void abstract setAttribute(java.lang.String name, java.lang.Object value);
Parameters name
The name of the attribute.
value
The value of the attribute.
Allows the user to set specific attributes on the underlying implementation. An attribute in this context is defined to be an option that the implementation provides. An IllegalArgumentException is thrown if the underlying implementation doesn't recognize the attribute.
Method setErrorListener(ErrorListener) public void abstract setErrorListener(javax.xml.transform.ErrorListener listener);
72
Final 1.0.0
Package javax.xml.transform
Parameters listener
The new error listener.
Set the error event listener for the TransformerFactory, which is used for the processing of transformation instructions, and not for the transformation itself. An IllegalArgumentException is thrown if the ErrorListener listener is null.
Method setFeature(String, boolean) public void abstract setFeature(java.lang.String name, boolean value) throws TransformerConfigurationException;
Parameters name
Feature name.
value
Is feature state true or false.
Exceptions TransformerConfigura tionException
if this TransformerFactory68 or the Transformer62s or Templates it creates cannot support this feature.
NullPointerException
If the name parameter is null.
Set a feature for this TransformerFactory68 and Transformer62s or Templates created by this factory. Feature names are fully qualified java.net.URIs. Implementations may define their own features. An javax.xml.trans form.TransformerConfigurationException [ Exception TransformerConfigurationException] is thrown if this Trans formerFactory68 or the Transformer62s or Templates it creates cannot support the feature. It is possible for an TransformerFactory68 to expose a feature value but be unable to change its state. All implementations are required to support the javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING feature. When the feature is: •
true: the implementation will limit XML processing to conform to implementation limits and behave in a secure fashion as defined by the implementation. Examples include resolving user defined style sheets and functions. If XML processing is limited for security reasons, it will be reported via a call to the registered javax.xml.transform.Er rorListener.fatalError [ Method fatalError(javax.xml.transform.TransformerException)]. See javax.xml.trans form.TransformerFactory.setErrorListener [ Method setErrorListener(javax.xml.transform.ErrorListener)].
•
false: the implementation will processing XML according to the XML specifications without regard to possible implementation limits.
Method setURIResolver(URIResolver) public void abstract setURIResolver(javax.xml.transform.URIResolver resolver);
Parameters resolver
An object that implements the URIResolver interface, or null.
73
Final 1.0.0
Package javax.xml.transform
Set an object that is used by default during the transformation to resolve URIs used in document(), xsl:import, or xsl:include.
Interface ErrorListener To provide customized error handling, implement this interface and use the setErrorListener method to register an instance of the implmentation with the javax.xml.transform.Transformer [ Class Transformer]. The Transformer 62 then reports all errors and warnings through this interface. If an application does not register its own custom ErrorListener, the default ErrorListener is used which reports all warnings and errors to System.err and does not throw any Exceptions. Applications are strongly encouraged to register and use ErrorListeners that insure proper behavior for warnings and errors. For transformation errors, a Transformer62 must use this interface instead of throwing an Exception: it is up to the application to decide whether to throw an Exception for different types of errors and warnings. Note however that the Transformer62 is not required to continue with the transformation after a call to javax.xml.transform.Er rorListener.fatalError [ Method fatalError(javax.xml.transform.TransformerException)]. Transformer62s may use this mechanism to report XML parsing errors as well as transformation errors.
Synopsis implements public ErrorListener { public void warning(javax.xml.transform.TransformerException exception) throws TransformerException; public void error(javax.xml.transform.TransformerException exception) throws TransformerException; public void fatalError(javax.xml.transform.TransformerException exception) throws TransformerException; } Inheritance Path javax.xml.transform.ErrorListener
Members Method error(TransformerException) public void error(javax.xml.transform.TransformerException exception) throws TransformerException;
Parameters exception
The error information encapsulated in a transformer exception.
74
Final 1.0.0
Package javax.xml.transform
Exceptions javax.xml.transform.Trans formerException See Also
if the application chooses to discontinue the transformation.
javax.xml.transform.TransformerException [Exception TransformerException]
Receive notification of a recoverable error. The transformer must continue to try and provide normal transformation after invoking this method. It should still be possible for the application to process the document through to the end if no other errors are encountered.
Method fatalError(TransformerException) public void fatalError(javax.xml.transform.TransformerException exception) throws TransformerException;
Parameters exception
The error information encapsulated in a TransformerException.
Exceptions javax.xml.transform.Trans formerException See Also
if the application chooses to discontinue the transformation.
javax.xml.transform.TransformerException [Exception TransformerException]
Receive notification of a non-recoverable error. The Transformer62 must continue to try and provide normal transformation after invoking this method. It should still be possible for the application to process the document through to the end if no other errors are encountered, but there is no guarantee that the output will be useable.
Method warning(TransformerException) public void warning(javax.xml.transform.TransformerException exception) throws TransformerException;
Parameters exception
The warning information encapsulated in a transformer exception.
Exceptions javax.xml.transform.Trans formerException See Also
if the application chooses to discontinue the transformation.
javax.xml.transform.TransformerException [Exception TransformerException]
Receive notification of a warning. javax.xml.transform.Transformer [ Class Transformer] can use this method to report conditions that are not errors or fatal errors. The default behaviour is to take no action.
75
Final 1.0.0
Package javax.xml.transform
After invoking this method, the Transformer must continue with the transformation. It should still be possible for the application to process the document through to the end.
Interface Result An object that implements this interface contains the information needed to build a transformation result tree.
Synopsis implements public Result { public void setSystemId(java.lang.String systemId); public String getSystemId(); } Author
Jeff Suttor [
[email protected]]
Inheritance Path javax.xml.transform.Result
Members Field PI_DISABLE_OUTPUT_ESCAPING static java.lang.String PI_DISABLE_OUTPUT_ESCAPING ; See Also
disable-output-escaping in XSLT Specification [http://www.w3.org/TR/xslt#disable-output-escaping]
The name of the processing instruction that is sent if the result tree disables output escaping. Normally, result tree serialization escapes & and < (and possibly other characters) when outputting text nodes. This ensures that the output is well-formed XML. However, it is sometimes convenient to be able to produce output that is almost, but not quite well-formed XML; for example, the output may include ill-formed sections that will be transformed into well-formed XML by a subsequent non-XML aware process. If a processing instruction is sent with this name, serialization should be output without any escaping. Result DOM trees may also have PI_DISABLE_OUTPUT_ESCAPING and PI_ENABLE_OUTPUT_ESCAPING inserted into the tree.
Field PI_ENABLE_OUTPUT_ESCAPING static java.lang.String PI_ENABLE_OUTPUT_ESCAPING ; See Also
disable-output-escaping in XSLT Specification [http://www.w3.org/TR/xslt#disable-output-escaping]
The name of the processing instruction that is sent if the result tree enables output escaping at some point after having received a PI_DISABLE_OUTPUT_ESCAPING processing instruction.
Method getSystemId() public String getSystemId();
76
Final 1.0.0
Package javax.xml.transform
Get the system identifier that was set with setSystemId.
Method setSystemId(String) public void setSystemId(java.lang.String systemId);
Parameters systemId
The system identifier as a URI string.
Set the system identifier for this Result. If the Result is not to be written to a file, the system identifier is optional. The application may still want to provide one, however, for use in error messages and warnings, or to resolve relative output identifiers.
Interface Source An object that implements this interface contains the information needed to act as source input (XML source or trans formation instructions).
Synopsis implements public Source { public void setSystemId(java.lang.String systemId); public String getSystemId(); } Inheritance Path javax.xml.transform.Source
Members Method getSystemId() public String getSystemId(); Get the system identifier that was set with setSystemId.
Method setSystemId(String) public void setSystemId(java.lang.String systemId);
Parameters systemId
The system identifier as a URL string.
Set the system identifier for this Source.
77
Final 1.0.0
Package javax.xml.transform
The system identifier is optional if the source does not get its > All get*(*) methods operate in the current scope for Namespace URI and prefix resolution. Note that a Namespace URI can be bound to multiple prefixes in the current scope. This can occur when multiple XM LConstants.XMLNS_ATTRIBUTE ("xmlns") Namespace declarations occur in the same Start-Tag and refer to the same Namespace URI. e.g.
This can also occur when the same Namespace URI is used in multiple XMLConstants.XMLNS_ATTRIBUTE ("xmlns") Namespace declarations in the logical parent element hierarchy. e.g.
...
A prefix can only be bound to a single Namespace URI in the current scope.
Synopsis implements public NamespaceContext { public String getNamespaceURI(java.lang.String prefix); public String getPrefix(java.lang.String namespaceURI); public Iterator getPrefixes(java.lang.String namespaceURI); } Author
Jeff Suttor [mailto:
[email protected]]
Version
$Revision: 1.4.16.1 $, $Date: 2004/06/28 18:20:38 $
123
Final 1.0.0
Package javax.xml.namespace
Since
1.5
See Also
javax.XMLConstants for declarations of common XML values, XML Schema Part2: >
"external-spec" is the type of all ulinks that refer to external specifications
"organization" is the type of all ulinks that refer to organ izations
252
Final 1.0.0