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>
-
标签编写注意事项:
- 所有的xml元素都必须有结束标签
- xml对大小写敏感
- xml编写正确的嵌套
- 同级标签以缩进对齐
- 元素名称可以包含字母、数字或者其他字符
- 元素名称不能以数字或者标点开始
- 元素名称不能包含空格
-
我们现在会定义xml文件并且在xml文件中存入节点的数据,然后我们现在要学会通过xml程序去解析我们的配置的xml文件信息!
4.xml解析技术分类
-
DOM:
- 基于xml文档结构的解析方式
- 适用于多次访问xml文档
- 特点:比较消耗资源
-
SAX:
- 基于事件的解析方式
- 适用于大数据量的xml文档
- 特点:占用资源少,内存消耗小
-
DOM4j:
- 非常优秀的java xml ApI
- 性能优秀,功能强大
- 开发源代码
5.解析xml技术
-
定义xml
-
在项目下右键新建source folder可编译文件夹,和src目录一样,都是可以用来编译源码的文件夹,一般用于存储项目的配置信息,比如xml文件、properties文件。
-
编写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底层技术更简单!
-
首先导入DOM4j.jar
-
测试
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(); } }