XML 的解析简介
解析方式dom和sax
- dom方式解析
- 根据XML层级结构,在内存中分配一个树形结构,把xml标签,属性,文本封装成对象
- 缺点:如果文件过大,造成内存溢出
- 优点:很方便增删改查
- sax方式解析:
- 采用事件驱动,边度边解析,从上到下一行一行的解析,解析到一个对象,返回对象名
- 缺点:不能实现增删改操作
- 优点:如果文件过大不会造成内存溢出,方便实现查询操作
- 要想解析XML,首先需要解析器
- 不同的公司和组织提出了针对dom和sax方式的解析器,通过api方式提供
- sun公司针对dom和sax提供了:jaxp
- dom4j组织陈对dom和sax提供了:dom4j
- jdom组织针对dom和sax提供了:jdom
jaxp的api查看
- jaxp是Javase的一部分:在javax.xml.parsers包下,常用的有4个类
- 针对dom的类
- DocumentBuilder这是一个抽象类,解析器,这个类的 实例是通过DocumentBuilderFactory.newDocumentBuilder()方法获取的。
- parse(File f)将传入的文件解析
- parse(String uri)根据传入文件的索引解析
- DocumentBuilderFactory解析器工厂
- DocumentBuilder这是一个抽象类,解析器,这个类的 实例是通过DocumentBuilderFactory.newDocumentBuilder()方法获取的。
- 针对sax 的类
- SAXParser
- SAXParserFactory
jaxp 的应用
使用jaxp查询节点
- 使用解析器工厂创建解析器
- 使用解析器的解析方法获得document对象
- 使用dom对象的方法赛选节点返回一个节点数组
- 使用for循环遍历
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class Demo1 { public static void main(String[] args) throws Exception { // 使用解析器工厂创建 解析器 DocumentBuilderFactory instance = DocumentBuilderFactory.newInstance(); DocumentBuilder document = instance.newDocumentBuilder(); // 使用解析器的解析方法解析xml Document parse = document.parse("src\\haha.xml"); // 指定要解析的元素 NodeList list = parse.getElementsByTagName("name"); // 遍历节点 for (int i = 0; i < list.getLength(); i++) { // 获得节点 Node item = list.item(i); // 查看节点的内容 String text = item.getTextContent(); // 打印节点内容 System.out.println(text); } } }
给xml文件中添加某一个节点
- 获得要添加节点的父节点来进行操作
- 创建要添加的 节点和内容
- 把要添加的节点和节点内容建立联系,把要添加的节点和符节点建立联系
解析的操作都是在内存层面的,所以需要 使用Transformer类的transform(Source xmlSource, Result outputTarget) 方法进行回写到源文件
/** * 给XML文件中添加一个节点name * @author lien * @return void * @throws Exception * * */ public static void add() throws Exception { DocumentBuilderFactory newInstance = DocumentBuilderFactory.newInstance(); DocumentBuilder newDocumentBuilder = newInstance.newDocumentBuilder(); Document parse = newDocumentBuilder.parse("src\\haha.xml"); // 获得了要操作的父节点 Node item = parse.getElementsByTagName("author").item(0); // 创建一个要添加的子节点 Element createElement = parse.createElement("name"); Text createTextNode = parse.createTextNode("李恩"); // 将创建的节点和内容建立联系 createElement.appendChild(createTextNode); // 将创建的节点和父节点建立联系 item.appendChild(createElement); /* * 因为我们这里的操作知识对内存中的xml进行解析 * 所以还需要进行回写才能在xml文件显示我们添加的节点 * 这里需要使用的是Transforme类,请查看api文档 * */ //通过使用TransformerFactory工厂获得Transform实例 TransformerFactory newInstance2 = TransformerFactory.newInstance(); Transformer newTransformer = newInstance2.newTransformer(); //回写操作,这种方式可以 添加,但是 格式不正常,不建议使用 newTransformer.transform(new DOMSource(parse), new StreamResult("src\\haha.xml")); }
缺点:使用 这种方式 添加修改等操作,xml格式会很乱的.例如:下图中添加的节点name,显示格式很乱。
- 修改操作
- 将一个子节点中的内容修改为自己想要的,基本操作和添加相同
- 只是使用了setTextContent(String)方法设置了内容
- 一定要回写操作
/**
<ul><li>修改一个节点的内容</li>
<li>@author lien</li>
<li>@return void</li>
<li>@throws Exception </li>
<li>
<ul><li>*/
public static void alter() throws Exception {
DocumentBuilderFactory instance = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = instance.newDocumentBuilder();
Document document = documentBuilder.parse("src\\haha.xml");
Node node = document.getElementsByTagName("name").item(0);
node.setTextContent("张学友");
//回写操作
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("src\\haha.xml"));
}
- 删除节点,使用了document的removeChile(Node)方法,写 回写操作
- 替换节点,使用了document的replaceChild(Node newChile,Node oldChild)方法,写回写操作
遍历节点操作
/** * 遍历操作 * @author lien * @throws IOException * @throws SAXException * @throws ParserConfigurationException * */ public static void dump(Node document) { if(document.getNodeType() == Node.ELEMENT_NODE) { // xmL中的所有空格换行都被当作节点 处理,所以判断如果是一个元素节点再打印 System.out.println(document.getNodeName()); } NodeList nodes = document.getChildNodes(); // 遍历节点集合 for(int i = 0 ;i < nodes.getLength(); i++) { Node item = nodes.item(i); dump(item); } }
ajxp针对sax的解析
- 事件驱动,边读边解析,主要是两个类
- sax不能实现增删改操作,主要是查询操作
- SAXparser 解析器,
- parse(String uri, DefaultHandler dh)方法解析
- url 要解析的文件 地址
- DefaultHandler 事件处理器,一半要创建一个类继承这个事件处理器重写三个方法,这样可以实现输出的功能等等;
- parse(String uri, DefaultHandler dh)方法解析
- SAXpsrserFactory 解析器工厂
sax解析过程
- 当解析到开始标签的时候,会自动执行startElement方法
- 当解析到结束标签的时候,会自动执行 endElement方法
当解析到文本的时候,会自动执行characters方法,
- 实例:使用sax方式解析xml,遍历所有的元素,并且打印输出
实例:使用sax方式解析xml,遍历指定的标签的内容
/* * 使用sax方式解析,获取 标签name的值 * * */ public static void pars() throws Exception { SAXParserFactory instance = SAXParserFactory.newInstance(); SAXParser parser = instance.newSAXParser(); parser.parse("src\\haha.xml", new MyDefaultHandler1()); } //定义了一个事件处理器重写了 三个方法,为了方便输出 class MyDefaultHandler1 extends DefaultHandler{ boolean flag = false; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); if("name".equals(qName)) { flag = true; } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); flag = false; } public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); if(flag == true) { System.out.println(new String(ch,start,length)); } }