苦尽甘来 一个月学通JavaWeb(四 XML)

夜光序言:

人总是需要一些仪式的,仪式给人庄重感和宿命感,给人信心。

没有人会理解她这种莫名其妙的执念——想象中那样平等的相识是多么的重要。

 

苦尽甘来 一个月学通JavaWeb(四 XML)

正文:

SAX

SAX概述

 

1 SAX解析原理

首先我们想一下,DOM解析器是不是需要把XML文档遍历一次,然后把每次读取到的数据转换成节点对象(到底哪一种节点对象,这要看解析时遇到了什么东西)保存起来,最后生成一个Document对象返回。也就是说,当你调用了builder.parse(“a.xml”)后,这个方法就会把XML文档中的数据转换成节点对象保存起来,然后生成一个Document对象。这个解析XML文档的过程在parse()方法调用结束后也就结束了。我们的工作是在解析之后,开始对Document对象进行操作。

但是SAX不同,当SAX解析器的parse()方法调用结束后,不会给我们一个Document对象,而是什么都不给。SAX不会把XML数据保存到内存中,如果我们的解析工作是在SAX解析器的parse()方法调用结束后开始,那么就已经晚了~~凉凉献给自己~~

 

这说明我们必须在SAX解析XML文档的同时完成我们的工作。

SAX解析器在解析XML文档的过程中,读取到XML文档的一个部分后,会调用ContentHandler(内部处理器)中的方法。例如当SAX解析到一个元素的开始标签时,它会调用ContentHandler的startElement()方法;在解析到一个元素的结束标签时会调用ContentHandler的endElement()方法。

ContentHandler是一个接口,我们的工作是编写该接口的实现类,然后创建实现类的对象,在SAX解析器开始解析之前,把我们写的内容处理类对象交给SAX解析器,这样在解析过程中,我们的内容处理中的方法就会被调用了。

 

2 获取SAX解析器

与DOM相同,你应该通过JAXP获取SAX解析器,而不是直接使用特定厂商的SAX解析器。JAXP查找特定厂商的SAX解析器实现的方式与查找DOM解析器实现的方式完全相同~~

SAXParserFactory factory = SAXParserFactory.newInstance();

javax.xml.parsers.SAXParser parser = factory.newSAXParser();

parser.parse("src/students.xml", new MyContentHandler());

 

  上面代码中,MyContentHandler就是我们自己需要编写的ContentHandler的实现类对象。

 

3 内容处理器

org.xml.sax.ContentHandler中的方法:不用背诵,看看即可,洒脱一笑

  1. void setDocumentLocator(Locator locator):与定位相关,例如获取行数、实体、标识等信息,我们可以忽略他的存在;
  2. void startDocument() throws SAXException:文档开始解析之前被调用;
  3. void endDocument() throws SAXException:文档解析结束之后被调用;
  4. void startPrefixMapping(String prefix,String uri)throws SAXException:与名称空间相关,忽略;
  5. void endPrefixMapping(String prefix) throws SAXException:与名称空间相关,忽略;
  6. void startElement(String uri,String local,String qName,Attributes atts)throws SAXException:开始解析一个元素时被调用,其中uri、local这两个参数与名称空间相关,可以忽略。qName表示当前元素的名称,atts表示当前元素的属性集合;
  7. void endElement(String uri,String localName,String qName)throws SAXException:一个元素解析结束后会被调用;
  8. void characters(char[] ch,int start,int length)throws SAXException:解析到文本数据时会被调用,ch表示当前XML文档所有内容对应的字符数组,不只是当前文本元素的内容。start表示当前文本数据在整个XML文档中的开始下载位置,length是当前文本数据的长度;
  9. void ignorableWhitespace(char[] ch,int start,int length)throws SAXException:解析到空白文本数据时会被调用,可以忽略!
  10. void processingInstruction(String target,String data)throws SAXException:解析到处理指令时会被调用,可以忽略!
  11. void skippedEntity(String name)throws SAXException:解析到实体时会被调用,可以忽略!

 

org.xml.sax.helpers.DefualtHandler对ContentHandler做了空实现,所以我们可以自定义内容处理器时可以继承DefaultHandler类。

SAX应用

 

  1. 测试SAX

public class SAXTest {

@Test

public void testSAX() throws ParserConfigurationException, SAXException, IOException {

SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser parser = factory.newSAXParser();

parser.parse("src/students.xml", new MyContentHandler());

}

private static class MyContentHandler extends DefaultHandler {

@Override

public void startDocument() throws SAXException {

System.out.println("开始解析...");

}

@Override

public void endDocument() throws SAXException {

System.out.println("解析结束...");

}

@Override

public void startElement(String uri, String localName, String qName,

Attributes atts) throws SAXException {

System.out.println(qName + "元素解析开始");

}

@Override

public void endElement(String uri, String localName, String qName)

throws SAXException {

System.out.println(qName + "元素解析结束");

}

@Override

public void characters(char[] ch, int start, int length)

throws SAXException {

String s = new String(ch, start, length);

if(s.trim().isEmpty()) {

return;

}

System.out.println("文本内容:" + s);

}

@Override

public void ignorableWhitespace(char[] ch, int start, int length)

throws SAXException {

 

}

@Override

public void processingInstruction(String target, String data)

throws SAXException {

System.out.println("处理指令");

}

}

}

 

2 使用SAX打印XML文档

public class SAXTest2 {

@Test

public void testSAX() throws 

ParserConfigurationException, SAXException, IOException {

SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser parser = factory.newSAXParser();

parser.parse("src/students.xml", new MyContentHandler());

}

private static class MyContentHandler extends DefaultHandler {

@Override

public void startDocument() throws SAXException {

System.out.println("<?xml version='1.0' encoding='utf-8'?>");

}

 

@Override

public void startElement(String uri, String localName, String qName,

Attributes atts) throws SAXException {

StringBuilder sb = new StringBuilder();

sb.append("<").append(qName);

for(int i = 0; i < atts.getLength(); i++) {

sb.append(" ");

sb.append(atts.getQName(i));

sb.append("=");

sb.append("'");

sb.append(atts.getValue(i));

sb.append("'");

}

sb.append(">");

System.out.print(sb);

}

 

@Override

public void endElement(String uri, String localName, String qName)

throws SAXException {

System.out.print("</" + qName + ">");

}

 

@Override

public void characters(char[] ch, int start, int length)

throws SAXException {

System.out.print(new String(ch, start, length));

}

}

}