告诉解析器在哪里可以找到模式 使用 JAXP 1.2 进行更有用的文档验证(2)实例
 
- UID
- 1066743
|

告诉解析器在哪里可以找到模式 使用 JAXP 1.2 进行更有用的文档验证(2)实例
SAX 示例演示了如何使用 JAXP 1.2 中的新特性,通过 SAX 解析器来验证文档。要使用 SAX 解析器来验证文档,请执行以下操作:
- 创建一个 SAXParserFactory 对象。
- 将 namespace-aware 和 validating 特性设置为 true。
- 获取 SAXParser 对象。
- 设置模式语言和模式源的特性(这是 JAXP 1.2 和模式中新出现的)。
- 解析文档。解析器必须有权访问 ErrorHandler 对象。
清单 2. ValidateSAX.java 演示了 JAXP 1.21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| package org.ananas.tips;
import java.io.*;
import org.xml.sax.*;
import javax.xml.parsers.*;
public class ValidateSAX
{
public static String SCHEMA_LANGUAGE =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
XML_SCHEMA =
"http://www.w3.org/2001/XMLSchema",
SCHEMA_SOURCE =
"http://java.sun.com/xml/jaxp/properties/schemaSource";
public final static void main(String[] args)
throws IOException, SAXException, ParserConfigurationException
{
if(args.length < 2)
{
System.err.println("usage is:");
System.err.println(" java -jar tips.jar -validatesax "
+ "input.xml schema.xsd");
return;
}
File input = new File(args[0]),
schema = new File(args[1]);
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
SAXParser parser = factory.newSAXParser();
try
{
parser.setProperty(SCHEMA_LANGUAGE,XML_SCHEMA);
parser.setProperty(SCHEMA_SOURCE,schema);
}
catch(SAXNotRecognizedException x)
{
System.err.println("Your SAX parser is not JAXP 1.2 compliant.");
}
parser.parse(input,new ErrorPrinter());
}
}
|
ErrorHandler 和验证validating 特性告诉解析器向其 ErrorHandler 对象报告验证错误。实际上,这意味着如果您不注册 ErrorHandler ,您就不会看到错误消息。有些程序员期望解析器在无法验证文档时抛出一个异常,但 SAX 解析器并不这么做。
要测试 ,需要一个符合 JAXP 1.2 的解析器。查看您最喜欢的解析器的文档,或者下载最新版本的 Apache Xerces(我使用 V2.4.0 来准备这篇技巧文章)。如果您的解析器不符合 JAXP 1.2,那么当您试图设置该特性时,它会抛出一个 SAXNotRecognizedException 异常。这提示您应该升级到最新版本的 Xerces。
仅仅注册了一个 DefaultHandler 对象,该对象只是在控制台上打印验证错误,如清单 3 所示。您的应用程序可以注册更有趣的处理程序,如一个处理文档内容的处理程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| package org.ananas.tips;
import java.text.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
public class ErrorPrinter
extends DefaultHandler
{
private MessageFormat message =
new MessageFormat("({0}: {1}, {2}): {3}");
private void print(SAXParseException x)
{
String msg = message.format(new Object[]
{
x.getSystemId(),
new Integer(x.getLineNumber()),
new Integer(x.getColumnNumber()),
x.getMessage()
});
System.out.println(msg);
}
public void warning(SAXParseException x)
{
print(x);
}
public void error(SAXParseException x)
{
print(x);
}
public void fatalError(SAXParseException x)
throws SAXParseException
{
print(x);
throw x;
}
}
|
DOM 会怎样呢?JAXP 1.2 也定义了用于 DOM 解析器的模式支持,如 中所示。这个过程非常类似于 SAX 解析器的过程,唯一的差异在于您是在工厂(factory)对象上设置属性而不是在解析器对象上设置特性。详细的过程是:
- 创建一个 DOMBuilderFactory 对象。
- 将 namespace-aware 和 validating 特性设置为 true 。
- 设置模式语言和模式源的属性。如果您的解析器不符合 JAXP 1.2,那么它将抛出一个 IllegalArgumentException 异常。
- 获取 DocumentBuilder 对象(解析器)。
- 向解析器注册 ErrorHandler 对象。
- 解析文档。
这个示例仅仅演示了验证。您的应用程序可以用解析树做更多有趣的事情。
清单 4. ValidateDOM.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| package org.ananas.tips;
import java.io.*;
import org.xml.sax.*;
import javax.xml.parsers.*;
public class ValidateDOM
{
public static String SCHEMA_LANGUAGE =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
XML_SCHEMA =
"http://www.w3.org/2001/XMLSchema",
SCHEMA_SOURCE =
"http://java.sun.com/xml/jaxp/properties/schemaSource";
public final static void main(String[] args)
throws IOException, SAXException, ParserConfigurationException
{
if(args.length < 2)
{
System.err.println("usage is:");
System.err.println(" java -jar tips.jar -validatedom "
+ "input.xml schema.xsd");
return;
}
File input = new File(args[0]),
schema = new File(args[1]);
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
try
{
factory.setAttribute(SCHEMA_LANGUAGE,XML_SCHEMA);
factory.setAttribute(SCHEMA_SOURCE,schema);
}
catch(IllegalArgumentException x)
{
System.err.println("Your DOM parser is not JAXP 1.2 compliant.");
}
DocumentBuilder parser = factory.newDocumentBuilder();
parser.setErrorHandler(new ErrorPrinter());
parser.parse(input);
}
}
|
开发更健壮的 XML 应用程序在使用 XML 模式实现健壮的验证时,请记住:(几乎是肯定地)当您的应用程序验证文档时,应用程序不应该取决于文档本身的正确性。更具体地说,它不应当靠拥有正确的 xsi:schemaLocation 属性的文档。 |
|
|
|
|
|