XML文件解析
1、XML文件要求
1、标签
- xml标签名称区分大小写,中间不能有空格,不能以数字开头
- xml标签一定要正确匹配
- 一个xml文件中只能有一个标签
2、属性
- 属性值必须以引号包含,不能省略,可以是单引号也可以是双引号
- 一个标签可以有多个属性,但不能出现重复的属性名
3、注释
<!-- xml注释 -->
- 4、xml中特殊字符,转义字符
5、CDATA块
作用: 可以让一些需要进行包含特殊字符的内容统一进行原样输出
6、处理指令
作用: 告诉xml解析如果解析xml文档
案例:<?xml-stylesheet type="text/css" href="1.css"?>
告诉xml解析该xml文档引用了哪个css文件
需要提前xml内容可以使用xml-stylesheet指令指令
2、XML解析
- 1、解析方式
- DOM解析
- SAX解析
2、XML解析工具
- DOM解析:
- JAXP(官方工具)
- JDOM工具(非官方)
- Dom4J(非官方)
- SAX解析
- Sax解析工具(oracle-sun公司官方)
- DOM解析:
3、DOM 解析
DOM解析原理:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一棵Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容。
使用步骤:
- 导入dom4j的核心包。dom4j-1.6.1.jar
- 编写Dom4j读取xml文件代码
节点信息:节点名称、节点类型 封装到 Node(父类)
- 标签节点封装为ELement对象(Node子类),含有子节点
- 属性节点封装为Attribute对象(Node子类)
文本对象封装为Text对象(Node子类)
节点: Iterator Element.nodeIterator(); //获取当前标签节点下的所有子节点 标签: Element Document.getRootElement(); //获取xml文档的根标签 Element ELement.element("标签名") //指定名称的第一个子标签 Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签 List<Element> Element.elements(); //获取所有子标签 属性: String Element.attributeValue("属性名") //获取指定名称的属性值 Attribute Element.attribute("属性名");//获取指定名称的属性对象 Attribute.getName() //获取属性名称 Attibute.getValue() //获取属性值 List<Attribute> Element.attributes(); //获取所有属性对象 Iterator<Attribute> Element.attibuteIterator(); //获取所有属性对象 文本: Element.getText(); //获取当前标签的文本 Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容
示例代码XML文件读取
得到节点信息
@Test
public void test1() {
try {
// 1、读取xml文档
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("./src/contact.xml"));
// 2. nodeIterator:得到当前节点下所有的子节点对象(不包括孙节点)
Iterator<Node> it = doc.nodeIterator();
while(it.hasNext()){
Node node = it.next();
String name = node.getName();
System.out.println(name);
// 继续取出下边的子节点
// 只有标签节点才有子节点
// 判断当前节点是否是标签节点
if(node instanceof Element){
Element elem = (Element)node;
Iterator<Node> it2 = elem.nodeIterator();
while(it2.hasNext()){
Node n = it2.next();
String nName = n.getName();
System.out.println(nName);
}
}
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
得到所有的标签
@Test
public void test2(){
try {
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("./src/contact.xml"));
Element rootElement = doc.getRootElement();
System.out.println(rootElement.getName());
Iterator<Node> it = rootElement.nodeIterator();
while(it.hasNext()){
Node node = it.next();
if(node instanceof Element){
Element el = (Element)node;
getChild(el);
}
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 获取节点下的所有子节点
public void getChild(Element elem){
System.out.println(elem.getName());
Iterator<Node> it = elem.nodeIterator();
while(it.hasNext()){
Node n = it.next();
if(n instanceof Element){
Element el = (Element)n;
getChild(el);
}
}
}
获取 标签 属性
@Test
public void test3(){
try {
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("./src/contact.xml"));
// 1. 获取根标签
Element rootElement = doc.getRootElement();
// 2. 获取指定名称标签(遇到的第一个)
Element element = rootElement.element("contact");
System.out.println(element.getName());
// 3.获取所有的指定名称的子标签
Iterator<Node> it = rootElement.elementIterator("contact");
while(it.hasNext()){
Node n = it.next();
System.out.println(n.getName());
}
// 4、获取所有的子标签(不包括孙标签)
List<Node> list = element.elements();
for(Node n:list){
System.out.println(n.getName());
}
// 5、获取属性
String attributeValue = element.attributeValue("id");
System.out.println(attributeValue);
// 获取指定名称的属性对象
Attribute attribute = element.attribute("id");
System.out.println(attribute.getName()+" : "+attribute.getValue());
// 获取节点的所有属性对象
List<Attribute> listAttri = element.attributes();
for(Attribute attr:listAttri){
System.out.println(attr.getName()+" : "+attr.getValue());
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
XML文件写出
写出内容到xml文档
XMLWriter writer = new XMLWriter(OutputStream, OutputForamt) wirter.write(Document);
修改xml文档的API
增加:
DocumentHelper.createDocument() 增加文档 addElement("名称") 增加标签 addAttribute("名称",“值”) 增加属性
修改:
Attribute.setValue("值") 修改属性值 Element.addAtribute("同名的属性名","值") 修改同名的属性值 Element.setText("内容") 修改文本内容
删除
Element.detach(); 删除标签 Attribute.detach(); 删除属性
XML文件修改
import java.io.FileOutputStream;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
/**
* 创建一个xml文件,并加入标签
* @author wsk
*
*/
public class Demo2 {
@Test
public void test1() throws Exception{
// 1、创建文档
Document doc = DocumentHelper.createDocument();
// 增加标签
Element rootElem = doc.addElement("contactList");
Element conElem = rootElem.addElement("contact");
// 添加属性
conElem.addAttribute("name", "abc");
// 修改属性
Attribute nameAttr = conElem.attribute("name");
nameAttr.setValue("123");
// 添加文本
conElem.addText("张安");
conElem.clearContent();// 清除文本内容
conElem.addText("李四");
// 删除:两种删除方式1.直接删除对象。2.调用父节点,用父节点删除子节点。
nameAttr.detach();
nameAttr.getParent().remove(nameAttr);
// 2、写出
FileOutputStream out = new FileOutputStream("./src/contact.xml");
// OutputFormat format = OutputFormat.createCompactFormat();//紧凑格式
OutputFormat format = OutputFormat.createPrettyPrint();//有换行格式
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
writer.write(doc);
writer.close();
}
}
3、XPath技术
问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦
- XPath作用:主要是用于快速获取所需的节点对象。
在dom4j中如何使用xPath技术
- 导入xPath支持jar包 。 jaxen-1.1-beta-6.jar
使用xpath方法
List<Node> selectNodes("xpath表达式");
查询多个节点对象Node selectSingleNode("xpath表达式");
查询一个节点对象
XPath 语法
/ 绝对路径: 表示从xml的根位置开始或子元素(一个层次结构)
// 相对路径 : 表示不分任何层次结构的选择元素。
* 通配符 : 表示匹配所有元素
[] 条件 : 表示选择什么条件下的元素
@ 属性 : 表示选择属性节点
and 关系 : 表示条件的与关系(等价于&&)
text() 文本 : 表示选择文本内容
示例
String xPath = "//@id"; // 选择id属性对象
xPath = "//contact[not(@id)]"; //选择没有id属性的contact对象
xPath = "//contact[@id='001' and @name='eric']"; // 选择id=‘001’ name='eric'的节点
xPath = "//name/text()"; // 选择name节点的文本
Element stu = (Element)doc.selectSingleNode("//student[@id='2']");
List<Node> list = doc.selectNodes("//contact");
4、SAX解析
DOM解析时,一次性把xml全部读入到内存中,然后在内存中构建Document树,不适合大文件的读取
SAX解析原理:加载一点读取一点,对内存要求较低
SAX解析工具
SAX解析工具,sun公司提供内置在jdk中。org.xml.sax.*
核心类:SAXParser类:用于读取和解析xml文件对象
- 创建SAXParser对象
SAXParser parser=SAXParserFactory.newInstanc().newSAXParser(); - 调用parse方法
parser.parse(new File(“./src/contact.xml”), new MyDefaultHandler());
一个类继承class 类名(extends DefaultHandler) 在调用是创建传进去
DefaultHandler类的API:
void startDocument() : 在读到文档开始时调用
void endDocument() :在读到文档结束时调用
void startElement(String uri, String localName, String qName, Attributes attributes) :读到开始标签时调用
void endElement(String uri, String localName, String qName) :读到结束标签时调用
void characters(char[] ch, int start, int length) : 读到文本内容时调用
SAX解析
原理: 加载一点,读取一点,处理一点。适合大容量文件的读取
SAX解析只能读取
SAX解析只能从上往下,按顺序读取,不能往回读
SAX解析基于事件的编程方法。java开发编码相对复杂。