DOM
解析器完整的读入XML文档,然后将其转换成一个树型的数据结构,对于大多数应用,DOM 都运行很好,但是,如果文档很大,并且处理算法又非常简单,可以在运行时解析节点,而不必看到完整的树形结构,那么我们应该使用流机制解析器(streaming parser),Java 类库提供的流解析机制有 SAX 解析器和 StAX 解析器,SAX 解析器是基于事件回调机制,而 StAX解析器提供了解析事件的迭代器。
- 使用SAX解析器
SAX
解析器在解析XML 输入的组成部分时会报告事件,在使用 SAX 解析器时,需要一个处理器来为不同的解析器事件定义事件动作,ContentHandler 接口定义了若干个在解析文档时解析器会调用的回调方法,我们可以使用
DefaultHandler
类,该类继承与
ContentHandler
并提供了默认实现,重要的方法如下:
- startDocument:在文档开始时调用一次
- endDocument:在文档结束时调用一次
- startElement:在遇到起始标签时调用,有3个描述元素名的参数,其中qName参数标识标签限定名,如果命名空间处理特性打开,则
uri
表示的是命名空间,localName 表示的是本地名。 - endElement:在遇到结束标签时调用,其参数和
startElement
一致 - characters:在每当遇到字符数据时调用,如果标签没有内容,但有子标签时,其中的空格会作为字符数据返回
示例代码如下:
- 事件处理类
public class CustomDefaultHandler extends DefaultHandler {
????????@Override
????????public
void
startDocument() throws SAXException {????????????????super.startDocument();
?
?????????????????System.out.println("call startDocument");
????????}
?
?????????@Override
????????public
void
endDocument() throws SAXException {????????????????super.endDocument();
????????????????System.out.println("call endDocument");
????????}
?
?????????@Override
????????public
void
characters(char[] ch, int start, int length) throws SAXException {????????????????super.characters(ch, start, length);
?
?????????????????String chs = new
String(ch, start, length);????????????????System.out.println("characters ch=" + chs + " start=" + start + " length=" + length);
????????}
?
?????????@Override
????????public
void
startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {????????????????super.startElement(uri, localName, qName, attributes);
?
?????????????????StringBuilder sb = new
StringBuilder();????????????????for (int i = 0; i < attributes.getLength(); i++) {
????????????????????????sb.append(attributes.getLocalName(i) + "=\"" + attributes.getValue(i) + "\"
");????????????????}
?
?????????????????System.out.println("startElement qName=" + qName + " Uri=" + uri + " localName=" + localName + " "
+ sb.toString());
????????}
?
?????????@Override
????????public
void
endElement(String uri, String localName, String qName) throws SAXException {????????????????super.endElement(uri, localName, qName);
?
?????????????????System.out.println("endElement " + qName);
????????}
}
- 调用类
try {
????????Path xmlPath = Paths.get("E:\\IDEA Workspace\\exampleiostream\\src\\main\\java\\org\\drsoft\\examples\\xml", "appParse.xml");
????????InputStream xmlStream = Files.newInputStream(xmlPath, StandardOpenOption.READ);
????????SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
????????SAXParser saxParser = saxParserFactory.newSAXParser();
????????saxParser.parse(xmlStream, new
CustomDefaultHandler());} catch (SAXException e) {
??????????e.printStackTrace();
} catch (ParserConfigurationException e) {
??????????e.printStackTrace();
} catch (IOException e) {
??????????e.printStackTrace();
}
- 使用StAX解析器
StAX
解析器时一种拉解析器(pull
parser),与安装事件处理器不同,只需要使用基本的循环来迭代所有事件,示例代码如下:try {
??????Path xmlPath = Paths.get("E:\\IDEA Workspace\\exampleiostream\\src\\main\\java\\org\\drsoft\\examples\\xml", "appParse.xml");
??????InputStream xmlStream = Files.newInputStream(xmlPath, StandardOpenOption.READ);
?
???????XMLInputFactory factory = XMLInputFactory.newFactory();
??????XMLStreamReader parser = factory.createXMLStreamReader(xmlStream);
?
???????while (parser.hasNext()) {
??????????????????int event = parser.next();
??????????????????switch (event) {
??????????????????????????case XMLStreamConstants.START_DOCUMENT:
????????????????????????????????????System.out.println("START_DOCUMENT Call");
????????????????????????????????????break;
?
???????????????????????????case XMLStreamConstants.END_DOCUMENT:
????????????????????????????????????System.out.println("END_DOCUMENT Call");
????????????????????????????????????break;
?
???????????????????????????case XMLStreamConstants.START_ELEMENT:
????????????????????????????????????StringBuilder sb = new
StringBuilder();????????????????????????????????????for (int i = 0; i < parser.getAttributeCount(); i++) {
????????????????????????????????????????????sb.append(parser.getAttributeName(i) + "=\"" + parser.getAttributeValue(i) + "\"
");????????????????????????????????????}
????????????????????????????????????System.out.println("START_ELEMENT qName=" + parser.getName() + " Uri="
+ parser.getNamespaceURI()?+ " localName=" + parser.getLocalName() + " attribute="
+ sb.toString());
????????????????????????????????????break;
?
???????????????????????????case XMLStreamConstants.END_ELEMENT:
????????????????????????????????????System.out.println("END_ELEMENT qName=" + parser.getName() + " Uri=" + parser.getNamespaceURI()
?????????????????????????????????????????????????????+ " localName=" + parser.getLocalName());
????????????????????????????????????break;
?
???????????????????????????case XMLStreamConstants.CHARACTERS:
????????????????????????????????????int start = parser.getTextStart();
????????????????????????????????????int length = parser.getTextLength();
????????????????????????????????????System.out.println("CHARACTERS text=" + new
String(parser.getTextCharacters(), start, length));????????????????????????????????????break;
????????????????}
??????}
} catch (IOException e) {
????????e.printStackTrace();
} catch (XMLStreamException e) {
??????e.printStackTrace();
}
?
??
?