XML技术总结


一、XML简介

  • 全称为可扩展标记语言(Extensible Markup Language)
  • XML是w3c组织发布的,允许用户自定义标签,一个标签用于描述一段数据。
  • XML常见应用:XML语言出现的根本目标在于描述现实生活中经常出现的有关系的数据,还经常用作框架中软件配置文件,以描述程序模块之间的关系。
  • XML是为了传输数据,html是为了展示数据。

用XML语言来描述数据如下图。
在这里插入图片描述

二、XML语法

(1)文档声明

<?xml version="1.0" encoding="UTF-8" standalone="yes ?>
  • version="1.0":用来声明版本
  • encoding="GB2312":说明文档的字符编码
  • standalone="yes":说明文档是否独立

(2)元素/标签

  • XML元素指的是xml文件中出现的标签,一个标签分为开始标签和结束标签。
  • 一个标签中可以嵌套若干子标签。但不允许交叉嵌套。
  • 格式良好的XML文档必须有且仅有一个根标签,其它标签都是这个跟标签的子孙标签。
  • 由于空格和换行都作为原始内容被处理,所以使用换行和缩进等方式来让原文件中的内容清晰可读的"良好"书写习惯可能要被迫改变。

元素命名规范:一个XML元素可以包含字母、数字以及其它一些可见字符,但必须遵守下面的一些规范
①区分大小写,例如<P><p>是两个不同的标记。
②不能以数字或"_"(下划线)等标点字符开头。
③不能以XML(或XML、或Xml等)开头。
④不能包含空格
⑤名称中间不能包含冒号(:)。

(3)属性

  • 一个标签可以有多个属性,每个属性都有它自己的名称和取值,例如<input name="text">
  • 属性值一定要用双引号(")或单引号(')引起来。
  • 定义属性必须遵循与标签相同的命名规范。

在XML技术中,标签属性所代表的信息,也可以被改成用子元素的形式来描述,例如:

<input>
		<name>text</name>
<input>

(4)注释

  • XML文件中注释采用:<!--注释内容-->
  • XML声明之前不能有注释,注释不能嵌套。

(5)CDATA区、特殊字符

CDATA区

在编写XML文件时,有些内容可能不想让解析引擎解析执行,而是当作原始内容处理,可以把这些内容放在CDATA区里面,对于CDATA区域内的内容,XML解析程序不会处理,而是直接原封不动的输出。

		<![CDATA[
			<href>
				<br/>
			</href>
		]]>

特殊字符

特殊字符 替代符号
& &amp;
< &lt;
> &gt;
" &quot;
&apos;

(5)处理指令(processing instruction)

  • 处理指令PI,用来指挥解析引擎如何解析XML文档内容。
  • 例如,在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,应用css文件显示xml文档内容。<?xml-stylesheet type="text/css" href="1.css"?>
  • 处理指令必须以"<?“作为开头,以”?>"作为结尾,XML声明语句就是最常见的一种处理指令。

三、XML解析

XML解析的方式

  • dom解析(Document Object Model,即文档对象模型)是W3C组织推荐的处理XML的一种方式。
  • sax解析(Simple API for XML)不是官方标准,但它是XML社区事实上的标准,几乎所有的XML解析器都支持它。
  • 基于已封装库的XML解析开发包(Jaxp、Jdom、dom4j)。

给出需要解析的demo.xml文件和EmpList.xml文件

demo.xml

<?xml version="1.0" encoding="UTF-8"?>
<employees>
	<employee id="0">
		<name>Alexia</name>
		<age>23</age>
		<sex>Female</sex>
		<weight>150</weight>
		<weight><a>160</a></weight>
	</employee>
	<employee id="1">
		<name height="178">Edward</name>
		<age>24</age>
		<sex>Male</sex>
	</employee>
	<employee id="2">
		<name>wjm</name>
		<age>23</age>
		<sex>Female</sex>
	</employee>
	<employee id="3">
		<name>wh</name>
		<age>24</age>
		<sex>Male</sex>
	</employee>
</employees>

EmpList.xml

<?xml version="1.0" encoding="UTF-8"?>
<list>
	<emp id="1">
		<name>张三</name>
		<age>34</age>
		<gender></gender>
		<salary>3000</salary>
	</emp>
	<emp id="2">
		<name>王五</name>
		<age>18</age>
		<gender></gender>
		<salary>6500</salary>
	</emp>
	<emp id="3">
		<name>赵六</name>
		<age>28</age>
		<gender></gender>
		<salary>4400</salary>
	</emp>
	<emp id="4">
		<name>钱七</name>
		<age>19</age>
		<gender></gender>
		<salary>12000</salary>
	</emp>
</list>

(1)使用DOM解析XML

DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。

优点:把XML文件在内存中构造成树形结构,可以遍历和修改节点。

缺点:如果文件比较大,内存有压力,解析的实际时间会比较长。

①.DOM编程的步骤

①创建一个DocumentBuilderFactory的对象.
②创建一个DocumentBuilder对象.
③通过DocumentBuilder对象的parse(String fileName)方法解析xml文件.

②.使用Dom解析xml–>DomXml.java

package com.demo;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * Dom解析Xml
 */
public class DomXml {
	public static void main(String[] args) throws Exception {
		// 1.[获得工厂对象]-->创建一个DocumentBuilderFactory的对象
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		// 设置由此工厂生成的解析器,忽略注释
		dbf.setIgnoringComments(true);
		// 忽略空格
		dbf.setIgnoringElementContentWhitespace(true);
		// 2.[获得DOM解析器对象]-->创建一个DocumentBuilder对象.
		DocumentBuilder builder = dbf.newDocumentBuilder();
		// 3.[调用DOM解析器对象解析XML文档]通过DocumentBuilder对象的parse(String fileName)方法解析xml文件.
		Document doc = builder.parse("src/com/demo.xml");
		// 获得根节点
		Element root = doc.getDocumentElement();
		System.out.println(root.getTagName());
		// 根据标签名获得节点集合
		NodeList nodeList = doc.getElementsByTagName("employee");
		System.out.println("employees节点个数:" + nodeList.getLength());
		// 遍历nodeList
		for (int i = 0; i < nodeList.getLength(); i++) {
			Element element = (Element) nodeList.item(i);
			// 获得id属性值
			String attribute = element.getAttribute("id");
			System.out.println("id:" + attribute);
			// 获取第一个employee
			if (i == 0) {
				// 获得元素下面的name文本
				System.out.println("name文本值:"+ element.getElementsByTagName("name").item(0).getFirstChild().getNodeValue());
				// 获得元素下面的sex文本
				System.out.println("sex文本值:"+ element.getElementsByTagName("sex").item(0).getFirstChild().getNodeValue());
				// 获得第一个weight里的文本值
				System.out.println("weight文本值:"+ element.getElementsByTagName("weight").item(0).getFirstChild().getNodeValue());
				// 获得第二个weight里的文本值
				System.out.println("weight中a的文本值:"+ element.getElementsByTagName("weight").item(1).getFirstChild().getFirstChild().getNodeValue());
			}
		}
	}
}

DOM解析效果↓
在这里插入图片描述

(2)使用SAX解析XML

SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会对文档进行处理。

优点:解析可以立即开始,速度快,没有内存压力。
缺点:不能对节点做修改。

①.SAX解析的步骤

1.创建SAX解析工厂

SAXParserFactory spf = SAXParserFactory.newInstance();

2.创建解析器对象

SAXParser saxParser = spf.newSAXParser();

3.通过解析器对象得到一个XML的读取器

XMLReader xmlReader = sp.getXMLReader();

4.设置读取器的事件处理器

xmlReader.setContentHandler(new BookParserHander());

5.解析XML文件

saxParser.parse(file, new SaxXml());

②.使用Sax解析xml–>SaxXml.java

package com.demo;

import java.io.File;

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;

public class SaxXml 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 attributes) throws SAXException {
		System.out.println("开始解析元素***"+qName);
	}
	public static void main(String[] args) throws Exception, Exception {
		//1.创建SAX解析工厂
		SAXParserFactory spf = SAXParserFactory.newInstance();
		//2.创建解析器对象
		SAXParser saxParser = spf.newSAXParser();
		//创建File指明要解析的xml
		File file = new File("src/com/demo.xml");
		//3.解析XML文件
		saxParser.parse(file, new SaxXml());
	}
}

SAX解析效果↓
在这里插入图片描述

(3)使用Dom4j库解析XML

  • Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来后独立开发的。与JDOM不同的是,dom4j使用接口和抽象父类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
  • Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也使用了Dom4j。
  • 使用Dom4j开发,需下载Dom4j相应的jar文件。

①.使用Dom4j解析xml–>TestDom4j.java

package com.demo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;

import com.entiry.Emp;

public class TestDom4j {
	public static void main(String[] args) throws Exception {
		// 创建SaxReader解析器
		SAXReader reader = new SAXReader();
		// 指明解析的文件,获得document文档
		Document doc = reader.read(new File("src/com/EmpList.xml"));
		// 获得根节点
		Element root = doc.getRootElement();
		// 获得根节点下所有子节点
		List<Element> elements = root.elements();
		// 创建List<Emp>保存所有员工对象
		List<Emp> list = new ArrayList<Emp>();
		// 遍历子节点
		for (Element element : elements) {
			// 先获得节点的属性再获取值
			String id = element.attribute("id").getValue();
			//直接根据节点名获得节点中文本值element.elementText("name");
			// 先获得节点再获得节点值
			String name = element.element("name").getText();
			String age = element.elementText("age");
			String gender = element.elementText("gender");
			String salary = element.elementText("salary");
			Emp emp = new Emp(Integer.parseInt(id), name,Integer.parseInt(age), gender, Double.parseDouble(salary));
			list.add(emp);
		}
		System.out.println(list);
	}
}

dom4j解析效果↓
在这里插入图片描述

②.创建文档,添加节点

	/**
	 * 添加子节点:addElement()
	 * 添加文本值:addText()
	 * 添加子节点,并设置文本addElement().addText()
	 * 添加属性:addAttribute(,)
	 */
	@Test
	public void testAdd() throws Exception{
		//list存放Emp对象
		List<Emp> emps = new ArrayList<Emp>();
		emps.add(new Emp(1,"张三",33,"男",9000.0));
		emps.add(new Emp(2,"李四",18,"女",8000.0));
		emps.add(new Emp(3,"王五",20,"男",10000.0));
		//创建文档对象
		Document doc = DocumentHelper.createDocument();
		//创建根节点
		Element root = doc.addElement("list");
		for (Emp emp : emps) {
			//向根元素中添加名为emp的子元素
			Element ele = root.addElement("emp");
			//为emp元素添加id属性,并设置属性值
			ele.addAttribute("id", emp.getId()+"");
			//添加子节点,并设置节点中的文本值
			ele.addElement("name").addText(emp.getName());
			ele.addElement("age").addText(emp.getAge()+"");
			ele.addElement("gender").addText(emp.getGender());
			ele.addElement("salary").addText(emp.getSalary()+"");
		}
		//通过XMLWriter生成物理文件
		FileOutputStream fos = new FileOutputStream("src/com/EmpList1.xml");
		XMLWriter writer = new XMLWriter();
		writer.setOutputStream(fos);
		//将文档写出到指定路径中
		writer.write(doc);
		writer.close();
	}

添加节点效果↓
在这里插入图片描述

③.修改节点和属性

	@Test
	public void testUpdate() throws Exception{
		SAXReader sax = new SAXReader();
		Document doc = sax.read("src/com/EmpList1.xml");
		//获取根节点
		Element root = doc.getRootElement();
		//获取下标为1的节点
		Element e2 = (Element)root.elements().get(1);
		//获取id属性和name节点
		Attribute id =e2.attribute("id");
		Element name = e2.element("name");
		System.out.println("id:"+id.getValue()+"     name:"+name.getText());
		//修改di属性和name节点
		id.setValue("222");
		name.setText("李四2号");
		System.out.println("id:"+id.getValue()+"     name:"+name.getText());
	}

修改后的效果↓

在这里插入图片描述

发布了328 篇原创文章 · 获赞 798 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/weixin_43691058/article/details/103413868