一、XML概念
可扩展标记语言(英文:eXtensible Markup Language,缩写:XML),是一种标记语言。标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。如何定义这些标记,既可以选择国际通用的标记语言,比如HTML,也可以使用像XML这样由相关人士自由决定的标记语言,这就是语言的可扩展性。XML是从标准通用标记语言(SGML)中简化修改出来的。它主要用到的有可扩展标记语言、可扩展样式语言(XSL)、XBRL和XPath等。
二、XML语法
1、标签
2、属性
3、注释
4、文档声明:?xml version=”1.0” encoding=”utf-8” ?>
5、转义字符:①<:<转义; ②>:>转义; ③“:&quto转义; ④&:&转义; ⑤空格: 转义;
6、CDATE块:![CDATE[内容]]> 将该内容原样显示
7、处理指令:?xml-stylesheet type=”text/css” href=”css文件.css”?> 提供css样式文件
三、解析
1、DOM解析(使用Dom4j解析工具,需要添加依赖库dom4j-1.6.1.jar)
(1)解析原理:将xml加载为Document树,通过Document对象得到节点对象,通过节点对象访问xml内容(标签,属性,文本,注释)
(2)主要的API方法
element(name)方法:获取指定名的标签 elementIterator():获取该节点所有子节点,返回一个迭代器 elements():获取所有子节点,返回List attributeValue(name):获取指定属性名的值,返回String attribute(name):获取指定名的属性对象,返回Attribute对象 attributes():获取当前标签所有属性,返回List attributeIterator():获取所有属性,返回迭代器 getText():获取该节点的文本 elementText(name):获取指定节点名的文本
(3)解析xml文件并将数据封装到一个对象中
a、创建解析器SAXReader实例,并获取xml文件 b、获取根节点标签,获得其所有的标签节点,然后进行遍历 c、根据节点的名称获取相应的值,将其赋值给对象的字段,然后存放在一个容器中
新建一个xml文件person.xml
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="001">
<age>18</age>
<name>张三</name>
</person>
<person id="008">
<age>20</age>
<name>李四</name>
</person>
</persons>
创建一个Person类
package dom_parse;
public class Person {
private String id;
private String name;
private int age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "[id="+id+",name="+name+",age="+age+"]";
}
}
将person.xml封装到Person对象中
package dom_parse;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/* * 将xml文件解析并将数据存在一个对象中 * * */
public class DomParse3 {
public static void main(String[] args) throws Exception {
toObject();
}
public static void toObject() throws Exception{
List<Person> persons = new ArrayList<>();
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("./src/person.xml"));
Element elem = doc.getRootElement();
Iterator<Element> it = elem.elementIterator();
while(it.hasNext()){
Person person = new Person();
Element element = it.next();
person.setId(element.attributeValue("id"));
person.setName(element.element("name").getText());
person.setAge(Integer.parseInt(element.element("age").getText()));
persons.add(person);
}
for(Person p : persons){
System.out.println(p.toString());
}
}
}
(4)写一个Document对象到XML文档中,并对xml内容进行增删改操作
步骤:使用XMLWriter对象,传入一个输出流对象(也可以指定输出格式OutputFormat,有两个静态方法:createCompactFormat()代表取出空格和换行;createPrettyPrint()代表原样输出,并且其对象调用setEncoding()可设置编码格式)
第一个方法写一个xml文件student.xml
第二个方法修改xml文件person.xml
package dom_parse;
import java.io.File;
import java.io.FileOutputStream;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/* * 写一个document文档,并将其进行增删改 * */
public class DomParse4 {
public static void main(String[] args) throws Exception {
writeXML();
// modifyXML();
}
public static void writeXML() throws Exception{
Document doc = DocumentHelper.createDocument();
//增加一个根标签
Element rootElem = doc.addElement("students");
//增加子标签
Element stuElem = rootElem.addElement("student");
stuElem.addAttribute("id","001");
//添加name标签
Element nameElem = stuElem.addElement("name");
nameElem.setText("张三");
//添加gender标签
Element gendElem = stuElem.addElement("gender");
gendElem.setText("男");
//添加class标签
Element classElem = stuElem.addElement("class");
classElem.setText("Java班");
FileOutputStream fis = new FileOutputStream(new File("./src/student.xml"));
XMLWriter writer = new XMLWriter(fis,OutputFormat.createPrettyPrint());
writer.write(doc);
if(writer!=null)
writer.close();
}
//修改xml文件
public static void modifyXML() throws Exception{
Document doc = new SAXReader().read(new File("./src/person.xml"));
Element rootElem = doc.getRootElement();
//修改第一个person的名字
Element per1Elem = (Element)rootElem.elements("person").get(0);
Element nameElem = per1Elem.element("name");
// nameElem.setText("王五");
//修改第二个person的属性
Element per2Elem = (Element)rootElem.elements("person").get(1);
per2Elem.attribute("id").setValue("008");
//1、删除第一个person的name标签
// per1Elem.element("name").detach();
//恢复name
// per1Elem.addElement("name").setText("张三");;
//2、删除第二个person的age标签
// Element ageElem = per2Elem.element("id");
// ageElem.getParent().remove(ageElem);
//
//恢复id
// per2Elem.addElement("age").setText("20");
FileOutputStream fis = new FileOutputStream(new File("./src/person.xml"));
XMLWriter writer = new XMLWriter(fis,OutputFormat.createPrettyPrint());
writer.write(doc);
if(writer!=null)
writer.close();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student id="001">
<name>张三</name>
<gender>男</gender>
<class>Java班</class>
</student>
</students>
2、SAX解析
(1)原理:基于事件处理的解析方式。
(2)使用SAX解析将xml文件打印出来
步骤: (1)创建解析器。自定义一个DefaultHandler的子类实现5方法(startDocument()、startElement()、endElement、characters()、endDocument) ①在startElement()方法中的参数qName表示标签名,attributes表示属性集合,如果有getQName可获得属性名,getValue可获得属性值 ②在characters()方法中可获得解析处之前的所有文本内容,当前文本的开始位置及长度 (2)创建一个SAXParser解析器,通过SAXParserFactory的一个静态方法newSAXParser()得到。SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); (3)调用parse方法,传入xml文件和解析器对象
打印person.xml
package com.sax_parse;
import java.io.File;
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文件打印出来 * */
public class SAXParse1 {
public static void main(String[] args) throws Exception {
parsewithSAX();
}
public static void parsewithSAX() throws Exception,SAXException{
//创建SAXParser对象
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
MyDefaultHandler handler = new MyDefaultHandler();
parser.parse(new File("./src/person.xml"),handler);
String content = handler.getContent();
System.out.println(content);
}
}
/* * * 自定义SAX事件处理器,实现五个解析方法 * */
class MyDefaultHandler extends DefaultHandler{
private StringBuffer sb = new StringBuffer();
public String getContent(){
return sb.toString();
}
/** * @param qName:开始标签的标签名 * @param attributes:属性列表 */
@Override
public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException {
sb.append("<"+qName);
//判断是否有属性
if(attributes != null){
for(int i=0;i<attributes.getLength();i++){
//得到属性名
String attrName = attributes.getQName(i);
String attrValue = attributes.getValue(i);
sb.append(" "+attrName+"=\""+attrValue+"\"");
}
}
sb.append(">");
}
@Override
public void endElement(String uri,String qName) throws SAXException {
//结束标签
sb.append("</"+qName+">");
}
/** * @param ch:表示读到之前的所有文本内容 * @param start:表示当前文本的开始位置 * @param length:表示当前文本内容的长度 * */
@Override
public void characters(char[] ch,int start,int length) throws SAXException {
sb.append(new String(ch,start,length));
}
}
3、Dom4j解析和SAX解析的区别
1、DOM解析 (1)原理:一次性加载xml文档,不适合大容量的文件读取 (2)DOM解析可以任意进行增删改查 (3)DOM解析可以随时读取任意位置的数据 (4)DOM解析是面向对象的方法 2、SAX解析 (1)原理:边加载,边读取和处理。适合大容量文件 (2)SAX解析只能读取数据 (3)SAX解析只能从上往下依次读取,不能返回 (4)SAX解析是基于事件的方法
三、xPath技术
1、定义:用于快速查找xml中的元素,使用时需要导入jaxen-1.1-beta-6.jar 和 dom4j压缩包
2、语法:
(1)/:类似于在一个文件系统中定位文件,如果路径以斜线/开始,那么该路径表示到一个元素的绝对路径。如:/AAA表示找到的第一个AAA标签 (2)//:表示文档中所有满足双斜线后规则的元素,相对路径。如//BBB指文档中所有BBB元素,不分结构层次 (3)* :表示选择所有由星号之前路径所定位的元素。如:/AAA/*指AAA下所有子元素 (4)[]:方括号里的表达式可以进一步定位元素,数字表示元素在选择集的位置,last()表示最后一个; not(@属性名):表示不包含该属性; text()=“文本”:指定文本; and:连接两个条件 (5)@:指定属性的前缀(可加属性名,或属性名及值)
3、使用
package dom_parse;
import java.io.File;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
/* * 使用xPath技术查找元素 * */
public class DomParse5 {
public static void main(String[] args) throws Exception {
serachwithxPath();
}
public static void serachwithxPath() throws Exception{
Document doc = new SAXReader().read(new File("./src/person.xml"));
//1、使用/ (绝对路径)
String xpath = "/persons";
List<Node> nodes = doc.selectNodes(xpath);
for(Node node : nodes){
System.out.println(node);
}
}
}
//2、使用// 相对路径
xpath = "//name";
//3、使用* 通配符
xpath = "//person/*";
//4、使用[] 查找属性id
xpath = "//person[@id]";