新:使用Dom4J的SAX解析XML
我就不详细写了
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("conf/emplist.xml"));
Element root = doc.getRootElement();
List<Element> list = root.elements("emp");
for(Element e:list) {
//1.获取e的子节点
Element nameEle = e.element("name");
//2.获取子节点的值
String name = nameEle.getTextTrim();
//1和2两步可以省略成下面这步:
String name = e.elementText("name");
//获取节点的属性的值
String key = e.attributeValue("path");
String value = e.attributeValue("className");
}
以下为原文:较原始的方法
解析流程及原理
- //根据xml的标签创建对应的实体类
- //创建SAX工厂
- //从工厂实例获取SAX解析器
- //创建Handler子类并new
- //重写此子类:将标签下对应的内容写入实体类中
- //解析
SAX解析xml文件只走一次,一次就解析完成,解析顺序是从上到下,逐行解析,解析标签,然后解析标签之间的内容(即使是空白、换行符都要解析出来),然后再解析标签。
SAX可以识别开始标签与结束标签,所以我们可以在startElement()与endElement()方法里很方便的做一些事情。
characters()方法用来读取两个相邻标签之间的内容(并不是读成对标签之间的内容),即使是空白,也读出来。例如:</person> </persons>,我们可以使用trim()将空白字符消除
使用一个变量tag来存储标签名,可以在characters()方法中对应当前的标签名,方便判断标签并读取数据。
案例演示
将下面xml使用SAX解析,将结果存放在实体类中。
<?xml version="1.0" encoding="UTF-8"?> <persons> <person> <name>周杰伦</name> <fans>3000w</fans> </person> <person> <name>蔡依林</name> <fans>2000w</fans> </person> </persons>
代码
其中 show方法不是重写方法,是自定义方法。
实体类:
package _20191224_review;
/**
* person.xml中Person标签的实体
*/
public class Person {
private String name;
private String fans;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFans() {
return fans;
}
public void setFans(String fans) {
this.fans = fans;
}
}
解析流程:
package _20191224_review;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* SAX
* xml解析
* 代码:36
*/
public class TestXmlSAX {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//从工厂中获取SAX
SAXParserFactory factory = SAXParserFactory.newInstance();
//从SAX中获取解析器
SAXParser parser = factory.newSAXParser();
//创建Handler子类,并实例化
PersonHandler handler = new PersonHandler();
//重写该类中的必要方法
//解析
parser.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("_20191224_review/person.xml"),handler);
//尝试获取数据
handler.show();
}
}
class PersonHandler extends DefaultHandler{
private List<Person> persons;
private String tag;
private Person person;
public PersonHandler() {
persons = new ArrayList<>();
}
@Override
public void startDocument() throws SAXException {
System.out.println("解析文档开始了");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
tag = qName;
System.out.println("元素开始-->"+tag);
if(tag.equals("person")) {
person = new Person();
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
tag = qName;
System.out.println("元素结束-->"+qName);
if(tag.equals("person")) {
persons.add(person);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String content = new String(ch,start,length);
if(content.trim().isEmpty()) {
return;
}
System.out.println("tag "+tag+" 内容:"+content);
if(tag.equals("name")) {
person.setName(content);
}
if(tag.equals("fans")) {
person.setFans(content);
}
}
public void show() {
Iterator it = persons.iterator();
while(it.hasNext()) {
Person p = (Person)it.next();
System.out.println("名字:"+p.getName()+" 粉丝数:"+p.getFans());
}
}
}
运行效果

另一个案例:拓展,加入反射
xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app> <servlet> <servlet-name>login</servlet-name> <servlet-class>_20191224_servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login</url-pattern> <url-pattern>/g</url-pattern> </servlet-mapping> <servlet> <servlet-name>reg</servlet-name> <servlet-class>_20191224_servlet.RegisterServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>reg</servlet-name> <url-pattern>/reg</url-pattern> </servlet-mapping> </web-app>
我们已经将xml的数据存在了handler里,接下来我们使用反射机制,来动态的创建对象,使得模拟登陆请求和注册请求。在这两个请求之下,创建不同的类。
先写一个接口
package _20191224_servlet;
public interface Servlet {
void service();
}
写两个实现类
登陆类
package _20191224_servlet;
public class LoginServlet implements Servlet{
@Override
public void service() {
System.out.println("LoginServlet");
}
}
注册类
package _20191224_servlet;
public class RegisterServlet implements Servlet {
@Override
public void service() {
System.out.println("RegisterServlet");
}
}
上下文类:
将原本储存在List中的数据转换为存储在Map,根据不同的请求获取不同的类名,使用反射动态创建类。
package _20191224_servlet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 上下文:servlet-mapping下的url-pattern会找到对应的servlet-name
* 然后找到servlet标签中对应的servlet-name,然后找到对应的servlet-class
* @author TEDU
*代码:
*/
public class WebContext {
private List<Entity> entitys = null;
private List<Mapping> mappings = null;
//key-->servlet-name value-->servlet-class
private Map<String,String> entityMap = new HashMap<String,String>();
//url-->pattern value-->servlet-name
private Map<String,String> mappingMap = new HashMap<String,String>();
public WebContext() {
}
public WebContext(List<Entity> entitys, List<Mapping> mappings) {
this.entitys = entitys;
this.mappings = mappings;
//将entityList转为对应的Map
for(Entity entity : entitys) {
entityMap.put(entity.getName(),entity.getClazz());
}
//将MappingList转为对应的Map
for(Mapping mapping : mappings) {
for(String pattern : mapping.getPatterns()) {
mappingMap.put(pattern,mapping.getName());
}
}
}
/**
* 获取calss
* @param pattern
* @return
*/
public String getClazz(String pattern) {
String name = mappingMap.get(pattern);//丢pattern进去获取servlet-name
return entityMap.get(name);//丢servlet-name进去获取servlet-class
}
}
TestXmlSAXPro:解析xml
package _20191224_servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* 解析 web.xml 并做反射
* 代码:
*/
public class TestXmlSAXPro {
public static void main(String[] args) throws Exception {
//SAX工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//从工厂获取SAX解析器
SAXParser parser = factory.newSAXParser();
//创建Handler子类并new
WebHandler handler = new WebHandler();
//重写此类
//解析
parser.parse(Thread.currentThread().getContextClassLoader().getResourceAsStream("_20191224_servlet/web.xml"),handler);
//尝试获取结果
WebContext context = new WebContext(handler.getEntitys()
,handler.getMappings());
//改写的部分开始
//假设你输入了../login
String className = context.getClazz("/login");
System.out.println(className);
String className1 = context.getClazz("/g");
System.out.println(className1);
String className2 = context.getClazz("/reg");
System.out.println(className2);
//反射
Class<?> clz = Class.forName(className);
Servlet servlet = (Servlet)clz.getConstructor().newInstance();
System.out.println(servlet);
servlet.service();
//改写的部分结束
}
}
class WebHandler extends DefaultHandler{
private List<Mapping> mappings;//servlet-mapping 标签的集合实例
private List<Entity> entitys;//servlet标签的集合实例
private Mapping mapping;///servlet-mapping 标签的实例
private Entity entity;//servlet标签的实例
private String tag; //存储标签名的变量
private boolean isMapping = false;//标记当前标签是否为servlet-Mapping
public WebHandler(){
mappings = new ArrayList<>();
entitys = new ArrayList<>();
}
public List<Mapping> getMappings() {
return mappings;
}
public List<Entity> getEntitys() {
return entitys;
}
//开始标签
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
tag = qName;
if(tag.equals("servlet")) {
entity = new Entity();
}
if(tag.equals("servlet-mapping")) {
isMapping = true;
mapping = new Mapping();
}
}
//结束标签
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
tag = qName;
//如果是结束标签,则将实例添加到对应的集合中
if(tag.equals("servlet")) {
entitys.add(entity);
}
if(tag.equals("servlet-mapping")) {
mappings.add(mapping);
isMapping = false;
}
}
//每个标签(不分开始与结束标签)之间的内容
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String content = new String(ch,start,length).trim();
if(content.isEmpty()) return;
if(isMapping) { //如果是Mapping标签下的属性
if(tag.equals("servlet-name")) {
mapping.setName(content);
}
if(tag.equals("url-pattern")) {
mapping.addPattern(content);
}
}else {
if(tag.equals("servlet-name")) {
entity.setName(content);
}
if(tag.equals("servlet-class")) {
entity.setClazz(content);
}
}
}
}
Mapping类。
package _20191224_servlet;
import java.util.HashSet;
import java.util.Set;
public class Mapping {
private String name;
private Set<String> patterns;
public Mapping() {
patterns = new HashSet<>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<String> getPatterns() {
return patterns;
}
public void setPatterns(Set<String> patterns) {
this.patterns = patterns;
}
public void addPattern(String pattern) {
patterns.add(pattern);
}
}
Entity类:
package _20191224_servlet;
public class Entity {
private String name;
private String clazz;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
}
运行结果
