XML 验证是优秀文档创作的基准。给出 XML
文档含意的关键――同时也是验证的要点――是拥有一组控制文档的约束以及确保遵循这些约束。例如,只允许一个
page 元素时(表示一页内容)
page
元素的含意与允许多个
page
元素时(表示包含数百页的长文章) page 元素的含意不同。 有了 DTD 或
XML
模式,再加上验证语法分析器,就可以使文档在每个应用程序中都可以使用。
通过使用 SAX (the Simple API for
XML),可以容易地验证文档的约束并将该含意提供给一个或多个 XML
文档(请参阅
参考资料)。
在 XML 语法分析器中,验证在缺省情况下通常关闭,这是因为很多 XML
作者都不编写约束; 将其关闭可帮助避免产品环境中的冗长处理。
要打开验证,必须明确请求它。在本文中,我将演示如何使用 SAX API
来这样做。因为 SAX
是由事件驱动的,所以您需要在验证期间发生任何错误的时候得到通知,并对它作出反应。可以通过使用
SAX
ErrorHandler
接口来这样做,我将为您演示如何去做。
设置 SAX 特性是用 SAX 进行验证的关键。这通过 SAX 2.0 方法
setFeature() 完成。该方法将描述要设置功能的 URI 和
Boolean 值(
true 或
false )作为自变量。
请参阅
参考资料 中 SAX 定义的 URI
的联机列表。 该页面列出了您和我都感兴趣的特性。它的 String 常量是
http://xml.org/sax/features/validation ,如我先前提到的那样,
通常在缺省情况下,String 在语法分析器中是关闭的。 要请求 XML
语法分析器中的验证特性,只需将该特性的值设置为
true ,如清单 1 中所示。
清单 1. 请求验证
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class ValidateXML {
public static void main(String[] args) {
try {
// Create a new XML parser
XMLReader reader = XMLReaderFactory.createXMLReader();
// Request validation
reader.setFeature("http://xml.org/sax/features/validation", true);
// Parse the file as the first argument on the command-line
reader.parse(args[0]);
} catch (SAXException e) {
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
|
在按照“清单 1”进行更改之后,语法分析器将对文档进行验证,
但您可能不会得到它所遇到的任何问题的消息,因为这段代码不提供报告错误的方法。
当发生验证错误时――例如,发现禁用的元素――会发生 SAX 回调。
但是,如果不在该回调中编写要
做 某事的代码,则代码或应用程序客户机将得不到任何报告。
要做到这点,可实现
org.xml.sax.ErrorHandler 接口。
该接口有三个方法,这三个方法都用来接收警告和错误通知。 清单 2
在清单 1
中所示的源代码中添加一个类,并在语法分析器中注册该错误处理程序。
清单 2. 创建并注册 ErrorHandler
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class ValidateXML {
public static void main(String[] args) {
try {
// Create a new XML parser
XMLReader reader = XMLReaderFactory.createXMLReader();
// Request validation
reader.setFeature("http://xml.org/sax/features/validation", true);
// Register the error handler
reader.setErrorHandler(new MyErrorHandler());
// Parse the file as the first argument on the command-line
reader.parse(args[0]);
} catch (SAXException e) {
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
class MyErrorHandler implements ErrorHandler {
public void warning(SAXParseException exception) throws SAXException {
// Bring things to a crashing halt
System.out.println("**Parsing Warning**\n" +
" Line: " +
exception.getLineNumber() + "\n" +
" URI: " +
exception.getSystemId() + "\n" +
" Message: " +
exception.getMessage());
throw new SAXException("Warning encountered");
}
public void error(SAXParseException exception) throws SAXException {
// Bring things to a crashing halt
System.out.println("**Parsing Error**\n" +
" Line: " +
exception.getLineNumber() + "\n" +
" URI: " +
exception.getSystemId() + "\n" +
" Message: " +
exception.getMessage());
throw new SAXException("Error encountered");
}
public void fatalError(SAXParseException exception) throws SAXException {
// Bring things to a crashing halt
System.out.println("**Parsing Fatal Error**\n" +
" Line: " +
exception.getLineNumber() + "\n" +
" URI: " +
exception.getSystemId() + "\n" +
" Message: " +
exception.getMessage());
throw new SAXException("Fatal Error encountered");
}
}
|
这个
ErrorHandler 实现有些夸张,
因为当任何问题发生时,它都会使程序彻底停止。
我没有按通常作法将错误代码返回给父代应用程序,而是将错误打印到屏幕,然后退出程序。
在您的产品应用程序中,您可能需要一个更佳的解决方案。
但是,这三种方法可以帮助您确切地知道问题是什么以及问题发生在何处。
这就是使用
ErrorHandler 的全部。
打开验证特性,注册错误处理程序,就是这些。然后,您就在用 SAX 验证
XML 了。
- 您可以参阅本文在 developerWorks 全球站点上的
英文原文.
- 通过单击本页面顶部或底部的
讨论,可以评论本文。
- 仔细阅读
SAX
API。
- 仔细阅读 Doug Tidwell 的文章系列
Building an XML application中的 XML。
- 学习 developerWorks
XML 入门教程中的 XML 基础知识。
- 回答 17 个问题的
有关开发习惯的调查问卷 ,辅助 IBM 改进用于开发软件应用程序的 XML
工具和服务。
- 查看
IBM WebSphere Application Server中的语法分析原理。
Brett McLaughlin ( brett@newInstance.com) 是 Lutris Technologies 的 Enhydra 策略顾问和分布式系统体系结构方面的专家。他是 Java 和 XML (O'Reilly) 的作者。他还参加了,如 Java servlets、Enterprise JavaBeans 技术、XML 和商家对商家应用等技术的研究。他与 Jason Hunter 一起建立了 JDOM 项目,该项目为在 JAVA 应用程序中控制 XML 提供一个简单的 API。他还是 Apache Cocoon 项目和 EJBoss EJB 服务器的活跃开发人员以及 Apache Turbine 项目的共同创建者。