XML解析方式

一、在开发中xml一般作为配置文件,或传输时的数据结构,也可以用来存储数据等功能。XML的解析方式有一下几种

二、DOM解析XML

    1.DOM解析XML文件可以修改xml文件中的内容,但是需要将整个的文件树加载到内从中这样消耗计算机资源就比较大。

          优点

         允许应用程序对数据和结构做出更改。
         访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。

          缺点

         通常需要加载整个XML文档来构造层次,消耗资源大。

    2.DOM操作XML我们首先要熟悉几个接口: 

        org.w3c.dom.Node接口是所有的父接口
        org.w3c.dom.Attr是元素标签的属性
        org.w3c.dom.Comment是注释标签(setData()和getData()方法设置和获得注释内容)
        org.w3c.dom.Document表示整个xml文档(代表xml的根节点root)
        org.w3c.dom.Element表示文档中的一个元素标签
        org.w3c.dom.Text表示Element或Attr的文本内容。

    3.代码实例增加节点、删除节点、查找节点

// 加载xml到内存获得document的实例
    public static Document getDocument(File file)
    {
        DocumentBuilderFactory factory = null;
        DocumentBuilder builder = null;
        Document doc = null;
        try
        {
            // 建立解析工厂
            factory = DocumentBuilderFactory.newInstance();
            // 获得一个xml的解析器
            builder = factory.newDocumentBuilder();
            // 根据解析器获得document实例
            doc = builder.parse(file);
            
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        
        return doc;
    }
    
    // 将doc写入到xml文件中
    public static void writeXMLToFile(Document doc)
    {
        try
        {
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer former = factory.newTransformer();
            //transform两个参数,一个数据源一个写入目标
            former.transform(new DOMSource(doc), new StreamResult(new File("src//student.xml")));
            
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    
    // 查找xml中的元素
    public static void queryElementfromDoc(Document doc)
    {
        // 获得所有标签名为name 的元素
        NodeList list = doc.getElementsByTagName("name");
        Element element;
        for (int i = 0; i < list.getLength(); i++)
        {
            // 获得第i个元素
            element = (Element)list.item(i);
            String name = element.getTextContent();
            System.out.println(name);
        }
        
    }
    
    /**
     * <studnet> <name>hanchao</name> <age>25</age> <num>3434</num> </studnet> 添加一个student元素
     * 
     * @param doc
     */
    public static Document addElementforDoc(Document doc)
    {
        // 创建一个student节点<studnet></studnet>
        Element student = doc.createElement("student");
        // 创建子元素<name>fjia</name>
        Element name = doc.createElement("name");
        Element age = doc.createElement("age");
        Element num = doc.createElement("num");
        // 给子元素设置值
        name.setTextContent("hanchao");
        age.setTextContent("25");
        num.setTextContent("3434");
        // 将子元素添加到student中
        student.appendChild(name);
        student.appendChild(age);
        student.appendChild(num);
        //获得要插入节点地方的父节点
        Element students = (Element)doc.getElementsByTagName("students").item(0);
        students.appendChild(student);
        return doc;
    }
    //删除节点
    public static Document removeElement(Document doc)
    {
        NodeList students = doc.getElementsByTagName("student");
        for(int i=0;i<students.getLength();i++)
        {
            Element student = (Element)students.item(i);
            String name =student.getElementsByTagName("name").item(0).getTextContent();
            if("hanchao".equals(name))
            {
                //通过父节点删除子节点
                student.getParentNode().removeChild(student);
                break;
            }
        }
        return doc;
    }


三、sax解析XMl

    1.sax解析,事件驱动,当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。

    2.优点:

        不需要等待所有数据都被处理,分析就能立即开始。
        只在读取数据时检查数据,不需要保存在内存中。
        可以在某个条件得到满足时停止解析,不必解析整个文档。
        效率和性能较高,能解析大于系统内存的文档。

      缺点:

       需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),文档越复杂程序就越复杂。
       单向导航,无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持XPath。

    3.sax解析实例

      首先根据xml文件定义解析器

public class MyHandler extends DefaultHandler {

	private Mp3 mp3;
	private List<Mp3> list;
	private String tag;
	private String value;
	
	public MyHandler(List<Mp3> list) {
		this.list = list;
	}

	//解析标签内容
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		value=new String(ch,start,length).trim();
		if("name".equals(tag))
		{
			mp3.setName(value);
		}
		if("author".equals(tag))
		{
			mp3.setAuthor(value);
		}
		if("size".equals(tag))
		{
			mp3.setSize(Integer.parseInt(value));
		}
		super.characters(ch, start, length);
	}

	//解析文档完毕
	@Override
	public void endDocument() throws SAXException {
		super.endDocument();
		System.out.println("解析完成");
	}

	//解析标签结束
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if("mp3".equals(localName))
		{
			list.add(mp3);
		}
		tag="";
		super.endElement(uri, localName, qName);
	}

	//开始解析xml文件
	@Override
	public void startDocument() throws SAXException {
		super.startDocument();
		System.out.println("开始解析");
	}

	//开始解析一个标签
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		tag=localName;
		if("mp3".equals(tag))
		{
			mp3=new Mp3();
		}
		super.startElement(uri, localName, qName, attributes);

	}

}


        加载xml文件用解析器解析

	public void getListMp3(List<Mp3> list)
	{
		//创建sax工厂
		SAXParserFactory factory=SAXParserFactory.newInstance();
		try {
			//工厂核心类
			SAXParser sp=factory.newSAXParser();
			//获得底层核心类
			XMLReader reader=sp.getXMLReader();
			
			//获得远程输入流
			//URL url=new URL(http://192.168.8.8/Test/rs.xml);
                           InputStream input = this.getClass().getClassLoader().getResourceAsStream("book.xml");  
			//边读取边解析
			reader.setContentHandler(new MyHandler(list));
			//reader.parse(new InputSource(url.openStream()));
                            reader.parse(input);                           
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

    4.dom4j解析xml

       简单易用,采用Java集合框架,并完全支持DOM、SAX和JAXP
        优点
       大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
       支持XPath。
       有很好的性能。
       缺点
       大量使用了接口,API较为复杂

    解析实例

	/**
	 * 读取Test.xml中第二个学生的属性
	 * @throws DocumentException 
	 */
	@Test
	public void read2() throws DocumentException{
		//读取xml文件
		SAXReader reader = new SAXReader();
		Document doc = reader.read(new File("Test.xml")); 
		//获得根节点
		Element root=doc.getRootElement();
		//获得根节点的子节点集合
		Element student=(Element)root.elements("student").get(1);
		//获得指定属性的对象
//		Attribute attr=student.attribute("id");
//		String value=attr.getValue();//获得属性值
		
		String value = student.attributeValue("id");
		System.out.println(value);
	}
	/**
	 * 在第一个学生标签中添加学号标签
	 * @throws Exception 
	 */
	@Test
	public void addElement() throws Exception{
		SAXReader reader=new SAXReader();
		Document doc=reader.read(new File("Test.xml"));
		
		Element root=doc.getRootElement();
		//获得第一个学生元素
		Element student=root.element("student");
		//添加元素并设置元素的值
		Element number=student.addElement("number");
		number.setText("3071817103");
		
		//避免乱码时首先指定格式化输出器的编码
		OutputFormat format=OutputFormat.createPrettyPrint();
		format.setEncoding("gb2312");			//把document写回到xml文件中,这里注意FileWriter写文件默认使用的是本地编码GB2312,应指定与文件的保存编码一直
		//XMLWriter writer=new XMLWriter(new FileWriter("Test.xml"));
		//XMLWriter writer=new XMLWriter(new OutputStreamWriter(new FileOutputStream(new File("Test.xml")), "gb2312"),format);
		XMLWriter writer=new XMLWriter(new FileOutputStream(new File("Test.xml")),format);
		writer.write(doc);
		writer.close();
		
	}
	/**
	 * 在第一个学生标签中指定位置上添加学号标签
	 * @throws Exception 
	 */
	@Test
	public void addElement2() throws Exception{
		SAXReader reader=new SAXReader();
		Document doc=reader.read(new File("Test.xml"));
		
		Element root=doc.getRootElement();
		//获得第一个学生元素
		Element student=root.element("student");
		
		//创建标签
		Element like=DocumentHelper.createElement("like");
		like.setText("棒球");
		
		//向指定位置添加标签,这里只需添加到list中的指定位置
		List<Element> list=student.elements();
		list.add(2, like);
		
		//避免乱码时首先指定格式化输出器的编码
		OutputFormat format=OutputFormat.createPrettyPrint();
		format.setEncoding("gb2312");	
			
	    XMLWriter writer=new XMLWriter(new FileOutputStream(new File("Test.xml")),format);
		writer.write(doc);
		writer.close();
		
	}
	
	/**
	 * 删除上面添加的like节点
	 * @throws Exception 
	 */
	@Test
	public void deleteElement() throws Exception{
		SAXReader reader=new SAXReader();
		Document doc=reader.read(new File("Test.xml"));
		Element root=doc.getRootElement();
		Element student=root.element("student");
		Element like=student.element("like");
		student.remove(like); //用父节点删除子节点
		
		OutputFormat format=OutputFormat.createPrettyPrint();
		format.setEncoding("gb2312");
		
		XMLWriter writer=new XMLWriter(new FileOutputStream(new File("Test.xml")), format);
		writer.write(doc);
		writer.close();
	}
	/**
	 * 更新第二个学生的姓名
	 * @throws Exception 
	 */
	@Test
	public void updateElement() throws Exception{
		SAXReader reader=new SAXReader();
		Document doc=reader.read(new File("Test.xml"));
		Element root=doc.getRootElement();
		Element student=(Element)root.elements("student").get(1);
		Element name=student.element("name");
		name.setText("李刚");
		
		OutputFormat format=OutputFormat.createPrettyPrint();
		format.setEncoding("gb2312");
		
		XMLWriter writer=new XMLWriter(new FileOutputStream(new File("Test.xml")), format);
		writer.write(doc);
		writer.close();
	}

    支持xpath可以方便的查找指定元素

	/**
	 * 修改用户密码
	 * 
	 * @param account
	 * @param pass
	 * @return
	 */
	public static boolean modifyPass(Account account, String pass)
	{
		boolean b = false;
		SAXReader reader = new SAXReader();
		try
		{
			Document doc = reader.read(new File("users.xml"));
			Element element = (Element) doc
			        .selectSingleNode("//user[@username='"
			                + account.getUsername() + "' and @password='"
			                + account.getPassword() + "']");
			Attribute attpass = element.attribute("password");
			attpass.setValue(pass);
			Login.account.setPassword(pass);
			OutputFormat format = OutputFormat.createPrettyPrint();
			format.setEncoding("UTF-8");
			XMLWriter writer = new XMLWriter(new FileOutputStream(new File(
			        "users.xml")), format);
			writer.write(doc);
			writer.close();
			b = true;

		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return b;
	}




 

 

 

 

 



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值