xml基础

来源:互联网 发布:知乎 material design 编辑:程序博客网 时间:2024/05/13 05:27

Validation The javax.xml.validation API uses three classes to validate documents: SchemaFactory, Schema, and Validator. It also makes extensive use of the javax.xml.transform.Source interface from TrAX to represent the XML documents. In brief, a SchemaFactory reads the schema document (often an XML file) from which it creates a Schema object. The Schema object creates a Validator object. Finally, the Validator object validates an XML document represented as a Source. Listing 1 shows a simple program to validate a URL entered on the command line against the DocBook XSD schema. Listing 1. Validating an Extensible Hypertext Markup Language (XHTML) document import java.io.*; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.*; import org.xml.sax.SAXException; public class DocbookXSDCheck { public static void main(String[] args) throws SAXException, IOException { // 1. Lookup a factory for the W3C XML Schema language SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); // 2. Compile the schema. // Here the schema is loaded from a java.io.File, but you could use // a java.net.URL or a javax.xml.transform.Source instead. File schemaLocation = new File("/opt/xml/docbook/xsd/docbook.xsd"); Schema schema = factory.newSchema(schemaLocation); // 3. Get a validator from the schema. Validator validator = schema.newValidator(); // 4. Parse the document you want to check. Source source = new StreamSource(args[0]); // 5. Check the document try { validator.validate(source); System.out.println(args[0] + " is valid."); } catch (SAXException ex) { System.out.println(args[0] + " is not valid because "); System.out.println(ex.getMessage()); } } } Here's some typical output when checking an invalid document using the version of Xerces bundled with Java 2 Software Development Kit (JDK) 5.0: file:///Users/elharo/CS905/Course_Notes.xml is not valid because cvc-complex-type.2.3: Element 'legalnotice' cannot have character [children], because the type's content type is element-only. You can easily change the schema to validate against, the document to validate, and even the schema language. However, in all cases, validation follows these five steps: 1. Load a schema factory for the language the schema is written in. 2. Compile the schema from its source. 3. Create a validator from the compiled schema. 4. Create a Source object for the document you want to validate. A StreamSource is usually simplest. 5. Validate the input source. If the document is invalid, the validate() method throws a SAXException. Otherwise, it returns quietly. You can reuse the same validator and the same schema multiple times in series. However, neither class is thread-safe or reentrant. If you validate in multiple threads simultaneously, make sure each one has its own Validator and Schema objects. Validate against a document-specified schema Some documents specify the schema they expect to be validated against, typically using xsi:noNamespaceSchemaLocation and/or xsi:schemaLocation attributes like this: ... If you create a schema without specifying a URL, file, or source, then the Java language creates one that looks in the document being validated to find the schema it should use. For example: SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); Schema schema = factory.newSchema(); However, normally this isn't what you want. Usually the document consumer should choose the schema, not the document producer. Furthermore, this approach works only for XSD. All other schema languages require an explicitly specified schema location. Abstract factories SchemaFactory is an abstract factory. The abstract factory design pattern enables this one API to support many different schema languages and object models. A single implementation usually supports only a subset of the numerous languages and models. However, once you learn the API for validating DOM documents against RELAX NG schemas (for instance), you can use the same API to validate JDOM documents against W3C schemas. For example, Listing 2 shows a program that validates DocBook documents against DocBook's RELAX NG schema. It's almost identical to Listing 1. The only things that have changed are the location of the schema and the URL that identifies the schema language. Listing 2. Validating a DocBook document using RELAX NG import java.io.*; import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.*; import org.xml.sax.SAXException; public class DocbookRELAXNGCheck { public static void main(String[] args) throws SAXException, IOException { // 1. Specify you want a factory for RELAX NG SchemaFactory factory = SchemaFactory.newInstance("http://relaxng.org/ns/structure/1.0"); // 2. Load the specific schema you want. // Here I load it from a java.io.File, but we could also use a // java.net.URL or a javax.xml.transform.Source File schemaLocation = new File("/opt/xml/docbook/rng/docbook.rng"); // 3. Compile the schema. Schema schema = factory.newSchema(schemaLocation); // 4. Get a validator from the schema. Validator validator = schema.newValidator(); // 5. Parse the document you want to check. String input = "file:///Users/elharo/Projects/workspace/CS905/build/Java_Course_Notes.xml"; // 6. Check the document try { validator.validate(source); System.out.println(input + " is valid."); } catch (SAXException ex) { System.out.println(input + " is not valid because "); System.out.println(ex.getMessage()); } } } If you run this program with the stock Sun JDK and no extra libraries, you'll probably see something like this: Exception in thread "main" java.lang.IllegalArgumentException: http://relaxng.org/ns/structure/1.0 at javax.xml.validation.SchemaFactory.newInstance(SchemaFactory.java:186) at DocbookRELAXNGCheck.main(DocbookRELAXNGCheck.java:14) This is because, out of the box, the JDK doesn't include a RELAX NG validator. When the schema language isn't recognized, SchemaFactory.newInstance() throws an IllegalArgumentException. However, if you install a RELAX NG library such as Jing and a JAXP 1.3 adapter, then it should produce the same answer the W3C schema does. Identify the schema language The javax.xml.constants class defines several constants to identify schema languages: • XMLConstants.W3C_XML_SCHEMA_NS_URI: http://www.w3.org/2001/XMLSchema • XMLConstants.RELAXNG_NS_URI: http://relaxng.org/ns/structure/1.0 • XMLConstants.XML_DTD_NS_URI: http://www.w3.org/TR/REC-xml This isn't a closed list. Implementations are free to add other URLs to this list to identify other schema languages. Typically, the URL is the namespace Uniform Resource Identifier (URI) for the schema language. For example, the URL http://www.ascc.net/xml/schematron identifies Schematron schemas. Sun's JDK 5 only supports XSD schemas. Although DTD validation is supported, it isn't accessible through the javax.xml.validation API. For DTDs, you have to use the regular SAX XMLReader class. However, you can install additional libraries that add support for these and other schema languages. How schema factories are located The Java programming language isn't limited to a single schema factory. When you pass a URI identifying a particular schema language to SchemaFactory.newInstance(), it searches the following locations in this order to find a matching factory: 1. The class named by the "javax.xml.validation.SchemaFactory:schemaURL" system property 2. The class named by the "javax.xml.validation.SchemaFactory:schemaURL" property found in the $java.home/lib/jaxp.properties file 3. javax.xml.validation.SchemaFactory service providers found in the META-INF/services directories of any available Java Archive (JAR) files 4. A platform default SchemaFactory, com.sun.org.apache.xerces.internal.jaxp.validation.xs.SchemaFactoryImpl in JDK 5 To add support for your own custom schema language and corresponding validator, all you have to do is write subclasses of SchemaFactory, Schema, and Validator that know how to process your schema language. Then, install your JAR in one of these four locations. This is useful for adding constraints that are more easily checked in a Turing-complete language like Java than in a declarative language like the W3C XML Schema language. You can define a mini-schema language, write a quick implementation, and plug it into the validation layer. Error handlers The default response from a schema is to throw a SAXException if there's a problem and do nothing if there isn't. However, you can provide a SAX ErrorHandler to receive more detailed information about the document's problems. For example, suppose you want to log all validation errors, but you don't want to stop processing when you encounter one. You can install an error handler such as that in Listing 3. Listing 3. An error handler that merely logs non-fatal validity errors import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class ForgivingErrorHandler implements ErrorHandler { public void warning(SAXParseException ex) { System.err.println(ex.getMessage()); } public void error(SAXParseException ex) { System.err.println(ex.getMessage()); } public void fatalError(SAXParseException ex) throws SAXException { throw ex; } } To install this error handler, you create an instance of it and pass that instance to the Validator's setErrorHandler() method: ErrorHandler lenient = new ForgivingErrorHandler(); validator.setErrorHandler(lenient); Schema augmentation Some schemas do more than validate. As well as providing a true-false answer to the question of whether a document is valid, they also augment the document with additional information. For example, they can provide default attribute values. They might also assign types like int or gYear to an element or attribute. The validator can create such type-augmented documents and write them onto a javax.xml.transform.Result object. All you need to do is pass a Result as the second argument to validate. For example, Listing 4 both validates an input document and creates an augmented DOM document from the combination of the input with the schema. Listing 4. Augmenting a document with a schema import java.io.*; import javax.xml.transform.dom.*; import javax.xml.validation.*; import javax.xml.parsers.*; import org.w3c.dom.*; import org.xml.sax.SAXException; public class DocbookXSDAugmenter { public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException { SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); File schemaLocation = new File("/opt/xml/docbook/xsd/docbook.xsd"); Schema schema = factory.newSchema(schemaLocation); Validator validator = schema.newValidator(); DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); // never forget this DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse(new File(args[0])); DOMSource source = new DOMSource(doc); DOMResult result = new DOMResult(); try { validator.validate(source, result); Document augmented = (Document) result.getNode(); // do whatever you need to do with the augmented document... } catch (SAXException ex) { System.out.println(args[0] + " is not valid because "); System.out.println(ex.getMessage()); } } } This procedure can't transform an arbitrary source into an arbitrary result. It doesn't work at all for stream sources and results. SAX sources can be augmented into SAX results, and DOM sources into DOM results; but SAX sources can't be augmented to DOM results or vice versa. If you need to do that, first augment into the matching result -- SAX for SAX and DOM for DOM -- and then use TrAX's identity transform to change the model. This technique isn't recommended, though. Putting all the information the document requires in the instance is far more reliable than splitting it between the instance and the schema. You might validate, but not everyone will. Type information The W3C XML Schema Language is heavily based on the notion of types. Elements and attributes are declared to be of type int, double, date, duration, person, PhoneNumber, or anything else you can imagine. The Java Validation API includes a means to report such types, although it's surprisingly independent of the rest of the package. Types are identified by an org.w3c.dom.TypeInfo object. This simple interface, summarized in Listing 5, tells you the local name and namespace URI of a type. You can also tell whether and how a type is derived from another type. Beyond that, understanding the type is up to your program. The Java language doesn't tell you what it means or convert the data to a Java type such as double or java.util.Date. Listing 5. The DOM TypeInfo interface package org.w3c.dom; public interface TypeInfo { public static final int DERIVATION_RESTRICTION; public static final int DERIVATION_EXTENSION; public static final int DERIVATION_UNION; public String getTypeName(); public String getTypeNamespace() public boolean isDerivedFrom(String namespace, String name, int derivationMethod); } To get TypeInfo objects, you ask the Schema object for a ValidatorHandler rather than a Validator. ValidatorHandler implements SAX's ContentHandler interface. Then, you install this handler in a SAX parser. You also install your own ContentHandler in the ValidatorHandler (not the parser); the ValidatorHandler will forward the augmented events on to your ContentHandler. The ValidatorHandler makes available a TypeInfoProvider that your ContentHandler can call at any time to find out the type of the current element or one of its attributes. It can also tell you whether an attribute is an ID, and whether the attribute was explicitly specified in the document or defaulted in from the schema. Listing 6 summarizes this class. Listing 6. The TypeInfoProvider class package javax.xml.validation; public abstract class TypeInfoProvider { public abstract TypeInfo getElementTypeInfo(); public abstract TypeInfo getAttributeTypeInfo(int index); public abstract boolean isIdAttribute(int index); public abstract boolean isSpecified(int index); } Finally, you parse the document with the SAX XMLReader. Listing 7 shows a simple program that uses all these classes and interfaces to print out the names of all the types of the elements in a document. Listing 7. Listing element types import java.io.*; import javax.xml.validation.*; import org.xml.sax.*; import org.xml.sax.helpers.*; public class TypeLister extends DefaultHandler { private TypeInfoProvider provider; public TypeLister(TypeInfoProvider provider) { this.provider = provider; } public static void main(String[] args) throws SAXException, IOException { SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); File schemaLocation = new File("/opt/xml/docbook/xsd/docbook.xsd"); Schema schema = factory.newSchema(schemaLocation); ValidatorHandler vHandler = schema.newValidatorHandler(); TypeInfoProvider provider = vHandler.getTypeInfoProvider(); ContentHandler cHandler = new TypeLister(provider); vHandler.setContentHandler(cHandler); XMLReader parser = XMLReaderFactory.createXMLReader(); parser.setContentHandler(vHandler); parser.parse(args[0]); } public void startElement(String namespace, String localName, String qualifiedName, Attributes atts) throws SAXException { String type = provider.getElementTypeInfo().getTypeName(); System.out.println(qualifiedName + ": " + type); } } Here's the start of the output from running this code on a typical DocBook document: book: #AnonType_book title: #AnonType_title subtitle: #AnonType_subtitle info: #AnonType_info copyright: #AnonType_copyright year: #AnonType_year holder: #AnonType_holder author: #AnonType_author personname: #AnonType_personname firstname: #AnonType_firstname othername: #AnonType_othername surname: #AnonType_surname personblurb: #AnonType_personblurb para: #AnonType_para link: #AnonType_link As you can see, the DocBook schema assigns most elements anonymous complex types. Obviously, this will vary from one schema to the next.

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 12306忘了密码和手机号怎么办 12306账号密码邮箱忘了怎么办 注册12306账号没有邮箱怎么办 12306忘了用户名和邮箱怎么办 12306忘记用户名和邮箱怎么办 12306证件号码已被注册怎么办 12306忘记手机号和邮箱怎么办 发邮件被对方服务器退回怎么办 铁路12306显示已注册怎么办 qq密码太长输不进去怎么办 淘宝买家收货地址填写不全怎么办 护士电子注册账户未激活怎么办 您的邮件被退回怎么办 给国外发信被退怎么办 苹果8icloud满了怎么办 吃人参回奶了怎么办 邮箱被黑客黑了怎么办 传图识字有表格怎么办 手机qq收件箱图片打不开怎么办 腾讯企业邮箱一直被攻击怎么办 qq邮箱发送文件太大怎么办 苹果手机邮箱被删除了怎么办 亚马逊卖家登录邮箱被盗怎么办 邮箱名字被注册了怎么办 忘了注册的邮箱名字怎么办 大众车钥匙丢了怎么办 锁柜钥匙丢了怎么办 邮箱的储存空间太小怎么办 扣扣邮箱不支持打开文件怎么办 邮箱大师群发不了邮件怎么办 邮政uk密码忘了怎么办 dns配置错误网页打不开怎么办 手机邮箱收不到邮件怎么办 wifi的那个用户密码错了怎么办 天翼校园客户端连不上怎么办 公司不小心外发邮件怎么办 steam账号被盗邮箱被改怎么办 steam被盗绑定邮箱被改怎么办 简历邮件发错了怎么办 发了简历不回复怎么办 发了简历没回复怎么办