zoukankan      html  css  js  c++  java
  • 71 SAX解析XML流程

    新:使用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");
    				}
    

      

    以下为原文:较原始的方法

    解析流程及原理

    1. //根据xml的标签创建对应的实体类
    2. //创建SAX工厂
    3. //从工厂实例获取SAX解析器
    4. //创建Handler子类并new
    5. //重写此子类:将标签下对应的内容写入实体类中
    6. //解析

    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;
    	}
    	
    }
    

      

    运行结果

  • 相关阅读:
    1301班 github安装及账户注册
    对于软件工程课程的疑问
    LeetCode50:Pow
    LeetCode49:字母异位词分组
    LeetCode46:全排列
    LeetCode38:外观数列
    LeetCode:有效的数独
    LeetCode34:在排序数组中查找元素的第一个位置和最后一个位置
    LeetCode33:搜索旋转排序数组
    LeetCode29:两数相除
  • 原文地址:https://www.cnblogs.com/Scorpicat/p/12090833.html
Copyright © 2011-2022 走看看