一、XML 基础
XML(EXtensible Markup Language),全称可扩展标记语言,可以实现不同系统之间的数据交换,与操作系统、编程语言的开发平台无关
作用:数据交互;配置应用程序和网站;Ajax基石
XML 编写注意事项:
- 所有 XML 元素都必须要有结束标签
- XML 标签对大小写敏感
- XML 必须正确嵌套,同级标签以缩进对齐
- 元素名称可以包含字母、数字或其他字符
- 元素名称不能以数字或标点符号开头
- 元素名称中不能有空格
- 一个元素可以有多个属性
-
属性值用双引号包裹,属性值中不能直接包含
<
、
”
、
&
,不建议包含
‘
、
>
XML 文档示例:
上图对应 XML 文档:
<?xml version="1.0" encoding="UTF-8"?>
<clothes>
<clothe size="S" height="身高<165"></clothe>
<clothe size="M" height="165<身高<175"></clothe>
<clothe size="L" height="175<身高<185"></clothe>
</clothes>
XML 命名空间:解决在复杂、大型XML文件中,出现名称相同,但是含义不同的元素
属性命名空间:除非带有前缀,否则属性属于所属的元素的命名空间
XML 解析器:——————回头记得补充!
- 非验证解析器:检查文档格式是否良好
- 验证解析器:使用DTD检查文档的有效性
解析 XML 技术:
-
DOM
基于XML文档树结构的解析;适用于多次访问的XML文档;特点:比较消耗资源 -
SAX
基于事件的解析;适用于大数据量的XML文档;特点:占用资源少,内存消耗小 -
DOM4J
非常优秀的Java XML API;性能优异、功能强大;开放源代码
二、DOM 解析 XML
使用 DOM 解析增删改查的示例:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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 ParseDom {
//document对象:将整个dom文档解析成的对象,该对象可以处理xml的增删改查功能
private Document dom = null;
//获取document对象
public void getDom(String path) {
//dom解析工厂来创建dom对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//由工厂创建解析器:该解析器可以将xml文件构造成document对象
try {
DocumentBuilder builder = factory.newDocumentBuilder();
//解析文档创建dom
dom = builder.parse(path);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//打印手机信息:先打印品牌,再遍历型号
public void getInfo(String path) {
getDom(path);
//获取标签brand的节点对象集合
NodeList brands = dom.getElementsByTagName("Brand");
for(int i = 0;i < brands.getLength();i++) {
Node brandNode = brands.item(i);
//获取品牌节点里面的属性
Element brandElement = (Element) brandNode;
String brandName = brandElement.getAttribute("name");
System.out.println(brandName);
//需要获取每个品牌里面的子元素型号,遍历打印型号
NodeList types = brandElement.getChildNodes();
for(int j = 0;j < types.getLength();j++) {
Node typeNode = types.item(j);
//判断是元素标签才能转换
// if(typeNode instanceof Element) {
if(typeNode.getNodeType() == Node.ELEMENT_NODE) {
Element typeElement = (Element) typeNode;
String typeName = typeElement.getAttribute("name");
System.out.println("\t"+typeName);
}
}
}
}
//添加节点:添加 三星 Note4 手机
public void addEle(String path,String brand,String type) {
getDom(path);
//创建品牌节点和属性
Element brandElement = dom.createElement("Brand");
brandElement.setAttribute("name", brand);
//创建型号节点和属性
Element typeElement = dom.createElement("Type");
typeElement.setAttribute("name", type);
//追加到相应的位置
brandElement.appendChild(typeElement);
dom.getElementsByTagName("PhoneInfo").item(0).appendChild(brandElement);
//保存到文件
saveXML(path);
}
//保存到文件 需要传输器将dom对象保存到指定文件中
public void saveXML(String path) {
//创建传输器工厂
TransformerFactory factory = TransformerFactory.newInstance();
//由工厂创建传输器
try {
Transformer transformer = factory.newTransformer();
//传输
DOMSource source = new DOMSource(dom);
//设置编码方式
transformer.setOutputProperty("encoding", "UTF-8");
StreamResult result = new StreamResult(new File(path));
transformer.transform(source, result);
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
//删除:根据标签名name属性删除元素,例如删除 苹果
public void deleteEle(String path,String delbrand) {
getDom(path);
NodeList brands = dom.getElementsByTagName("Brand");
for(int i = 0;i < brands.getLength();i++) {
Node brandNode = brands.item(i);
//获取品牌节点里面的属性
Element brandElement = (Element) brandNode;
String brandName = brandElement.getAttribute("name");
if(brandName.equals(delbrand)) {
brandElement.getParentNode().removeChild(brandElement);
// break;
}
}
saveXML(path);
}
public void change(String path,String oldbrand,String brand,String type) {
getDom(path);
Element newbrand = dom.createElement("Brand");
newbrand.setAttribute("name", brand);
Element newtype = dom.createElement("Type");
newtype.setAttribute("name", type);
newbrand.appendChild(newtype);
NodeList brands = dom.getElementsByTagName("Brand");
for(int i = 0;i < brands.getLength();i++) {
Node brandNode = brands.item(i);
//获取品牌节点里面的属性
Element brandElement = (Element) brandNode;
String brandName = brandElement.getAttribute("name");
if(brandName.equals(oldbrand)) {
brandElement.getParentNode().replaceChild(newbrand, brandElement);
}
}
saveXML(path);
}
public void change(String path,String label,String attrname,String oldattr,String newattr) {
getDom(path);
NodeList labels = dom.getElementsByTagName(label);
for(int i = 0;i < labels.getLength();i++) {
Node labelNode = labels.item(i);
//获取节点里面的属性
Element element = (Element) labelNode;
String attrValue = element.getAttribute(attrname);
if(attrValue.equals(oldattr)) {
element.setAttribute(attrname, newattr);
}
}
saveXML(path);
}
public static void main(String[] args) {
ParseDom parseDom = new ParseDom();
// parseDom.getDom("收藏信息.xml");
// System.out.println(parseDom.dom);
parseDom.addEle("收藏信息.xml","三星", "Note4");
//parseDom.deleteEle("收藏信息.xml", "oppo");
//parseDom.change("收藏信息.xml", "三星", "小米", "10");
//parseDom.change("收藏信息.xml", "Brand", "name", "三星", "华为");
//parseDom.change("收藏信息.xml", "Type", "name", "Note4", "MaxPro");
parseDom.getInfo("收藏信息.xml");
}
}
三、DOM4J 解析 XML
eclipse 使用 DOM4J 记得导入jar包:这里用的是 dom4j-1.6.1.jar
使用 DOM4J 解析增删改查的示例:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class ParseDom4J {
private Document dom = null;
//获取document对象
public void getDom(String path) {
SAXReader reader = new SAXReader();
try {
dom = reader.read(path);
} catch (DocumentException e) {
e.printStackTrace();
}
}
//读取文件信息
public void getInfo(String path) {
getDom(path);
//获取根节点
Element root = dom.getRootElement();
//获取brand节点的集合
Iterator<Element> brandsIt = root.elementIterator("Brand");
//用迭代器遍历brand
while(brandsIt.hasNext()) {
Element brand = brandsIt.next();
//打印name属性值
String brandName = brand.attributeValue("name");
System.out.println(brandName);
//打印型号
Iterator<Element> typeIt = brand.elementIterator("Type");
while(typeIt.hasNext()) {
Element type = typeIt.next();
String typeName = type.attributeValue("name");
System.out.println("\t"+typeName);
}
}
}
//添加节点:添加 小米 10 手机
public void addEle(String path,String brand,String type) {
getDom(path);
Element root = dom.getRootElement();
//创建品牌节点和属性,添加到根节点下面
Element brandElement = root.addElement("Brand");
brandElement.addAttribute("name", brand);
//创建型号节点和属性,添加到品牌节点下面
brandElement.addElement("Type").addAttribute("name", type);
//保存到文件
saveXML(path);
}
//保存到xml文件
public void saveXML(String path) {
XMLWriter writer;
try {
writer = new XMLWriter(new FileOutputStream(path));
writer.write(dom);
writer.flush();
writer.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//删除:根据标签名name属性删除元素,例如删除 三星
public void deleteEle(String path,String delbrand) {
getDom(path);
Element root = dom.getRootElement();
Iterator<Element> brandIt = root.elementIterator("Brand");
while(brandIt.hasNext()) {
Element brand = brandIt.next();
if(brand.attributeValue("name").equals(delbrand)) {
brand.getParent().remove(brand);
// break;
}
}
saveXML(path);
}
public void change(String path,String oldbrand,String oldtype,String newbrand,String newtype) {
getDom(path);
Element root = dom.getRootElement();
Iterator<Element> brandIt = root.elementIterator("Brand");
while(brandIt.hasNext()) {
Element brand = brandIt.next();
if(brand.attributeValue("name").equals(oldbrand)) {
brand.setAttributeValue("name", newbrand);
Iterator<Element> typeIt = brand.elementIterator("Type");
while(typeIt.hasNext()) {
Element type = typeIt.next();
if(type.attributeValue("name").equals(oldtype)) {
type.attribute("name").setValue(newtype);
}
}
}
}
saveXML(path);
}
public static void main(String[] args) {
ParseDom4J parseDom4J = new ParseDom4J();
// parseDom4J.getDom("收藏信息.xml");
// System.out.println(parseDom4J.dom);
parseDom4J.addEle("收藏信息.xml", "小米", "10");
//parseDom4J.deleteEle("收藏信息.xml", "三星");
//parseDom4J.change("收藏信息.xml", "三星", "Galaxy", "oppo", "R5");
parseDom4J.getInfo("收藏信息.xml");
}
}
附:收藏信息(可能有点格式问题)及其文件位置
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<PhoneInfo>
<Brand name="华为">
<Type name="U8650"/>
<Type name="HW123"/>
<Type name="HW321"/>
</Brand>
<Brand name="荣耀"><Type name="p30"/></Brand><Brand name="oppo"><Type name="R5"/></Brand>
<Brand name="小米"><Type name="10"/></Brand>
</PhoneInfo>
(是直接放在 src 文件夹下的:src > 收藏信息.xml)
版权声明:本文为wzskqfzl_zg原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。