xml 文件除了给开发者看,更多的情况使用程序读取 xml 文件的内容。读取 xml 文档的过程就是 xml 解析
1 XML解析方式
Java库提供了两种XML解析器:
1.1 树型解析器:DOM 解析
DOM 解析器一次性把整个xml文档加载进内存,然后在内存中构建一个 Document 的对象树,通过 Document 对象,得到树上的节点对象,通过节点对象访问(操作)到 xml 文档的内容
1.2 流机制解析器:SAX 解析
DOM 解析对内存要求较高,处理大容量的 xml 文件容易溢出
SAX 解析原理是加载一点,读取一点,处理一点。对内存的要求较低。
2 DOM 解析
Document 对象是 XML 文档的树型结构在内存中的表示方式,它由实现了 Node 接口及其各种子接口的类的对象构成。
Document树只有一个根标签,树上的分支叫做节点(Node)
- 节点信息:节点名称,节点类型—>封装为 Node
- 标签节点:节点名称—>封装为 Element
- 属性节点:属性名称,属性值—>封装为 Attribute
- 文本节点:文本内容—>封装为 Text
2.1 DocumentBuilder
要读入一个 XML 文档,首先需要一个 DocumentBuilder 对象,可以从 DocumentBuilderFactory 获取
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
2.2 读取文档
从文件
File f = ...;
Doucument doc = builder.parse(f);
从URL
URL u = ...;
Document doc = builder.parse(u);
从任意输入流
InputStream in = ...;
Document doc = builder.parse(in);
2.3 分析文档
1)获取元素
根元素
Element root = doc.getDocumentElement();
子元素
返回子元素集合,包含元素间空白
NodeList children = root.getChildNodes();
忽略空白字符
for(int i = 0; i < children.getLengrh(); i++){
Node child = children.item(i);
if(child instanceif Element){
Element childElement = (Element)child;
...
}
}
getFirstChild\getLastChild
兄弟元素
getNextSibling
2)取值
标签名
String tagName = root.getTagName();
文本值
getData 获取存储在 Text 节点中的字符串
属性
getAttributes 返回包含了描述属性的 NamedNodeMap。
NamedNodeMap attributes = element.getAttributes();
for(int i = 0; i < attributes.getLengrh(); i++){
Node attribute = attributes.item(i);
String name = attribute.getNodeName();
String value = attribute.getNodeValue();
}
getAttribute(name)
如果文档很大,并且处理算法又非常简单,可以在运行时解析节点,而不必看到完整的树形结构,应该使用流机制解析器(streaming parser)。
Java类库提供的流机制解析器:老而弥坚的SAX解析器和添加到Java SE 6中的更现代化的StAX解析器。SAX解析器使用的是事件回调(event callback),而StAX解析器提供了遍历解析事件的迭代器,后者用起来通常更方便一些。
3 SAX 解析器
3.1 获得SAX解析器
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
3.2 解析文档
parser.parse(source, handler);
source 可以是一个文件、一个URL字符串或者是一个输入流。handler 属于 DefaultHandler 的一个子类,包括 ContentHandler,DTDHandler,EntityResolver,ErrorHandler。
ContentHandler 接口定义了若干个在解析文档时解析器会调用的回调方法。
- startElement 和 endElement 在每当遇到起始或终止标签时调用。
- characters 在每当遇到字符数据时调用。
- startDocument 和 endDocument 分别在文档开始和结束时各调用一次。
4 StAX 解析器
StAX 解析器是一种“拉解析器(pull parser)”
InputStream in = url.openStream();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader parser = factory.createXMLStreamReader(in);
while(parser.hasNext()){
int event = parser.next();
//Call parser methods
}
XMLStreamReader 的 getAttributeValue 获取当前元素属性
String units = parser.getAttributeValue(null, "units");