20.xml解析

java的xml解析

1.xml定义

  • xml(Extensible Markup Language)可扩展标记语言;可以通过xml来存储数据,一般用于项目或者框架的配置信息
  • 特点:
    • xml与操作系统、编程语言的开发平台无关
    • 实现不同系统之间的数据交换

2.Java中xml的作用

  • java项目中,xml文件一般都是用来存储一些项目的配置信息,不会键大量数据配置在xml中
  • 在我们后期需要学习的servlet中,我们需要通过配置web.xml文件实现一些任务的调度,或者我们后期需要学习的几乎所有是java框架都可以通过xml来完成框架的配置信息,比如jdbc我们通过xml来配置数据源信息,或者spring框架用xml来配置IOC关系也就是对象和对象之间的关系,当我们需要去修改对象和对象之间的关系,我们没有必要再去修改java代码,可以直接修改xml文件的配置关系就可以实现,没有必要重新编译java代码,而且降低了代码之间的耦合度。
  • 一个好的项目,需要有良好的扩展性,如果把所有的逻辑关系还有配置信息都写入代码中,会使程序的可扩展性变差,为了解决这个问题,xml就可以对这整个项目进行调度(比如Sring框架对xml的使用场景)
  • 使用xml可以作为数据的存储,但是现在一般不会用xml来存储数据,多数情况下用于项目中的配置信息

3.xml文档结构

<?xml version="1.0" encoding="UTF-8"?>
<book>
	<!-- 注释:图书 -->
	<book id="book01" name="wu">
		<author>无名</author>
		<title>java</title>
		<desription>从入门到精通</desription>
	</book>
		<book id="book02" name="wu">
		<author>无名</author>
		<title>mysql</title>
		<desription>从入门到精通</desription>
	</book>
</book>
  • 标签编写注意事项:

    1. 所有的xml元素都必须有结束标签
    2. xml对大小写敏感
    3. xml编写正确的嵌套
    4. 同级标签以缩进对齐
    5. 元素名称可以包含字母、数字或者其他字符
    6. 元素名称不能以数字或者标点开始
    7. 元素名称不能包含空格
  • 我们现在会定义xml文件并且在xml文件中存入节点的数据,然后我们现在要学会通过xml程序去解析我们的配置的xml文件信息!

4.xml解析技术分类

  • DOM:

    • 基于xml文档结构的解析方式
    • 适用于多次访问xml文档
    • 特点:比较消耗资源
  • SAX:

    • 基于事件的解析方式
    • 适用于大数据量的xml文档
    • 特点:占用资源少,内存消耗小
  • DOM4j:

    • 非常优秀的java xml ApI
    • 性能优秀,功能强大
    • 开发源代码

5.解析xml技术

  • 定义xml

    1. 在项目下右键新建source folder可编译文件夹,和src目录一样,都是可以用来编译源码的文件夹,一般用于存储项目的配置信息,比如xml文件、properties文件。

    2. 编写xml文件

      <?xml version="1.0" encoding="UTF-8" standalone="no"?> <PhoneInfo> 	
          <Brand id="001" name="苹果"> 
          	<Type name="iPhone4"/> 
          	<Type name="iPhone5"/> 
          </Brand> 
          <Brand id="002" name="小米"> 
          	<Type name="micc"/> 
          	<Type name="小米10"/> 
          </Brand> 
      </PhoneInfo>
      

1.DOM解析

通过DOM方式实现对xml元素的增删改查

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class ParseXMLDemo {
	
//	private Document document;
	
	/**
	 * 	获取document文档对象
	 */
	public Document getDom() {
		Document document = null;
		//获取factory对象(单例的)
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			//在通过factory对象获取到builder对象
			//根据解析器工厂对象获取到解析器对象
			DocumentBuilder builder = factory.newDocumentBuilder();
			//再根据解析器对象获取到document对象
			document = builder.parse("resources/手机信息.xml");
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return document;
	}  
	
	/** 
	 * 	显示元素
	 */
	private void showINfo(Document document) {
		//通过document对象获取到brand节点,返回的是一个集合!
		NodeList brands = document.getElementsByTagName("Brand");
		for (int i = 0; i < brands.getLength(); i++) {
			Node node = brands.item(i);
			//循环遍历获取到每个Brand标签元素
			Element eleBrand = (Element)node;
			//获取到Brand元素的name属性值
			String brandName = eleBrand.getAttribute("name");
			System.out.println(brandName);
			NodeList types = eleBrand.getChildNodes();
			for (int j = 0; j < types.getLength(); j++) {
				Node typeNode = types.item(j);
				//判断这个子元素是不是一个元素节点(因为父节点内部可能有文本节点)
				if(typeNode.getNodeType()==Node.ELEMENT_NODE) {
					//获取Type节点
					Element eleType = (Element)typeNode;
					System.out.println("\t"+eleType.getAttribute("name"));
				}
			}
		}
	}
	
	/** 
	 * 	增加元素
	 */
	private void addElement(Document document) {
		//创建Brand元素
		Element brand = document.createElement("Brand");
		brand.setAttribute("name", "华为");
		//创建Type元素节点
		Element type = document.createElement("Type");
		type.setAttribute("name", "华为荣耀");
		//Brand节点里面增加Type子节点
		brand.appendChild(type);
		//将Brand以及子节点添加到phoneInfo子节点
		document.getElementsByTagName("phoneInfo").item(0).appendChild(brand);
		//借助IO流将内存的数据写入到文件中
		this.saveXMl(document,"resources/手机信息.xml");
	}
	
	/**
	 * 	将document内存中的新节点元素写入到xml文件中
	 * @param document
	 * @param path
	 */
	private void saveXMl(Document document, String path) {
		//单例模式获取factory对象,转换器工厂对象
		TransformerFactory factory = TransformerFactory.newInstance();
		factory.setAttribute("indent-number", 4);//设置缩进为4个单位
		try {
			//通过factory对象创建transformer对象,转换器对象
			Transformer transformer = factory.newTransformer();
			DOMSource source = new DOMSource(document);
			//设置转换格式
			transformer.setOutputProperty(OutputKeys.ENCODING,"utf-8");
			transformer.setOutputProperty(OutputKeys.INDENT, "YES");
			//字节输出流对象
			OutputStream os = new FileOutputStream(path);
			StreamResult result = new StreamResult(os);
			//通过transform()方法将指定的document内存里面存入的新标签节点通过IO流输出到指定文件
			transformer.transform(source, result);
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 	修改元素
	 * @param document
	 */
	private void updateElement(Document document) {
		NodeList brands = document.getElementsByTagName("Brand");
		for (int i = 0; i < brands.getLength(); i++) {
			Node brand = brands.item(i);
			Element brandEle = (Element)brand;
			brandEle.setAttribute("id", "00"+(i+1));
		}
		this.saveXMl(document, "resources/手机信息.xml");
	}

	
	/**
	 * 	删除元素
	 * @param document
	 */
	private void deleteElemnet(Document document) {
		NodeList brands = document.getElementsByTagName("Brand");
		for (int i = 0; i < brands.getLength(); i++) {
			Node brand = brands.item(i);
			Element brandEle = (Element)brand;
			if(brandEle.getAttribute("name").equals("华为")) {
				//找到华为的标签元素的父节点再去调用removeChild方法删除元素华为标签
				brandEle.getParentNode().removeChild(brandEle);
			}
		}
		this.saveXMl(document, "resources/手机信息.xml");
	}

	
	public static void main(String[] args) {
		ParseXMLDemo pd = new ParseXMLDemo();
		Document document = pd.getDom();
//		pd.addElement(document);
//		pd.updateElement(document);
		pd.deleteElemnet(document);
		pd.showINfo(document);
	}


}

2.DOM4j解析

如果你觉得DOM解析比较繁琐,那么你可以学习一下DOM4j解析方式,DOM4j是一个优秀的java解析的工具,他对DOM解析xml底层技术更简单!

  1. 首先导入DOM4j.jar

  2. 测试

    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Iterator;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.OutputFormat;
    import org.dom4j.io.SAXReader;
    import org.dom4j.io.XMLWriter;
    
    public class Dom4jDome {
    	
    	public Document document;//文档对象
    	
    	/**
    	 * 	获取document对象
    	 */
    	public void getDom() {
    		SAXReader saxReader = new SAXReader();
    		try {
    			document = saxReader.read(new File("手机信息.xml"));
    		} catch (DocumentException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	/**
    	 * 	解析xml文件
    	 */
    	private void showInfo() {
    		//获取到根节点对象
    		Element root = document.getRootElement();
    		//获取到了root元素内部元素brand标签集合
    		Iterator<Element> brands = root.elementIterator();
    		while(brands.hasNext()) {
    			Element brand = brands.next();
    			//根据Brand节点元素的name属性获取到name属性的值
    			String bramdEle = brand.attributeValue("name");
    			System.out.println("品牌:"+bramdEle);
    		}
    	}
    	/**
    	 * 	增加手机信息
    	 */
    	private void addNewPhoneInfo() {
    		//找到需要添加子元素的根节点
    		Element root = document.getRootElement();
    		Element el = root.addElement("Brand");
    		//给root节点内部添加节点Brand并且添加属性
    		el.addAttribute("name", "华为");
    		//给新添加Brand节点内部再去添加Type子节点并且添加属性
    		Element typeEle = el.addElement("type");
    		typeEle.addAttribute("name", "华为荣耀");
    		
    		this.saveXML("手机信息.xml");
    	}
    	
    	/** 
    	 * 	通过流将新建的节点元素写入到xml文件中
    	 */
    	private void saveXML(String path) {
    		OutputFormat format = OutputFormat.createPrettyPrint();
    		format.setEncoding("UTF-8");
    		try {
    			XMLWriter write = new XMLWriter(new FileWriter(path),format);
    			write.write(document);
    			write.flush();
    			write.close();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 	修改元素
    	 */
    	@SuppressWarnings("unchecked")
    	private void updateEle() {
    		Element root = document.getRootElement();
    		Iterator<Element> brands = root.elementIterator();
    		int id = 1;
    		while(brands.hasNext()) {
    			Element brand = brands.next();
    			brand.addAttribute("id", "00"+id);
    			id++;
    		}
    		this.saveXML("手机信息.xml");
    	}
    	
    	/**
    	 * 	根据name属性值删除指定的元素
    	 * @param string
    	 */
    	private void deleteEle(String name) {
    		Element root = document.getRootElement();
    		Iterator<Element> brands = root.elementIterator();
    		while(brands.hasNext()) {
    			Element brand = brands.next();
    			if(brand.attributeValue("name").equals(name)) {
    				brand.getParent().remove(brand);
    			}
    		}
    		this.saveXML("手机信息.xml");
    	}
    	
    	public static void main(String[] args) {
    		Dom4jDome dj = new Dom4jDome();
    		dj.getDom();
    //		dj.addNewPhoneInfo();
    //		dj.updateEle();
    		dj.deleteEle("华为");
    		dj.showInfo();
    	}
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值