一、什么是XML
- XML 指可扩展标记语言(EXtensible Markup Language)。
- XML 是一种很像HTML的标记语言。
- XML 的设计宗旨是传输数据,而不是显示数据。
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
- XML 是 W3C 的推荐标准
二、 XML 和 HTML 之间的差异
XML 不是 HTML 的替代。
XML 和 HTML 为不同的目的而设计:
- XML 被设计用来传输和存储数据,其焦点是数据的内容。
- HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息,而 XML 旨在传输信息。
三、XML用途
1.XML 把数据从 HTML 分离
如果需要在 HTML 文档中显示动态数据,那么每当数据改变时将花费大量的时间来编辑 HTML。
通过 XML,数据能够存储在独立的 XML 文件中。这样您就可以专注于使用 HTML/CSS 进行显示和布局,并确保修改底层数据不再需要对 HTML 进行任何的改变。
通过使用几行 JavaScript 代码,您就可以读取一个外部 XML 文件,并更新您的网页的数据内容。
2.XML 简化数据共享
在真实的世界中,计算机系统和数据使用不兼容的格式来存储数据。
XML 数据以纯文本格式进行存储,因此提供了一种独立于软件和硬件的数据存储方法。
这让创建不同应用程序可以共享的数据变得更加容易。
3.XML 简化数据传输
对开发人员来说,其中一项最费时的挑战一直是在互联网上的不兼容系统之间交换数据。
由于可以通过各种不兼容的应用程序来读取数据,以 XML 交换数据降低了这种复杂性。
4.XML 简化平台变更
升级到新的系统(硬件或软件平台),总是非常费时的。必须转换大量的数据,不兼容的数据经常会丢失。
XML 数据以文本格式存储。这使得 XML 在不损失数据的情况下,更容易扩展或升级到新的操作系统、新的应用程序或新的浏览器。
5.XML 使数据更有用
不同的应用程序都能够访问您的数据,不仅仅在 HTML 页中,也可以从 XML 数据源中进行访问。
通过 XML,数据可供各种阅读设备使用(掌上计算机、语音设备、新闻阅读器等),还可以供盲人或其他残障人士使用。
6.XML 用于创建新的互联网语言
很多新的互联网语言是通过 XML 创建的。
这里有一些实例:
- XHTML
- 用于描述可用的 Web 服务 的 WSDL
- 作为手持设备的标记语言的 WAP 和 WML
- 用于新闻 feed 的 RSS 语言
- 描述资本和本体的 RDF 和 OWL
- 用于描述针针对 Web 的多媒体 的 SMIL
四、XML语法简介
<?xml version="1.0" encoding="GB2312"?>
<PhoneInfo>
<Brand name="华为">
<Type name="U8650"/>
<Type name="HW123"/>
<Type name="HW321"/>
</Brand>
<Brand name="苹果">
<Type name="iPhone6"/>
<Type name="iPhone7"/>
<Type name="iPhone8"/>
</Brand>
</PhoneInfo>
注:存储一个手机信息表,第一行代表XML的规范及字符编码集;
PhoneInfo代表根节点,XML文件都是<></>或者单便签</>呈现;
<Type/>是<Brand></Band>是<PhoneInfo></PhoneInfo>的子节点,name是属性;
XML区分大小写,属性值必须用引号包起来
5.DOM解析
注:DOM解析是最基础也是较为消耗资源的方式,学会DOM解析其它的解析方式都能自行研究出
package xml02;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
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.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;
//根元素一般对应数据库表中的表名
//使用DOM解析XML文件
public class ParseXMLDemo {
// 声明:收藏信息.xml对应的Document对象
private Document document;
// 获得DOM树,获得Document对象
public void getDom() {
// 收藏解析器工厂; DocumentBuilderFactory是抽象类要用它的方法才能创建对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
// 根据解析器工厂获得解析器
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析器来解析XML文件获得Document对象
document = builder.parse("收藏信息.xml");
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 获取手机品牌及型号相关信息
public void showInfo() {
// 通过getElementsByTagName方法以Document做起点,先拿到指定所有的Brand节点,NodeList也是一个类似于集合的东西
NodeList brands = document.getElementsByTagName("Brand");
// 遍历brands,从中拿出每一个Brand;getLength方法可以从集合中拿出每一个节点元素
for (int i = 0; i < brands.getLength(); i++) {
Node node = brands.item(i);// item()方法返回每一个Node节点
Element eleBrand = (Element) node;// 将每一个Node节点强制转成元素节点
String brandName = eleBrand.getAttribute("name");// 根据getAttribute方法传入一个属性值返回一个String类型的属性值
System.out.println(brandName);
// 继续查找,找每个Brand的子节点出来
NodeList types = eleBrand.getChildNodes();
for (int j = 0; j < types.getLength(); j++) {
Node typeNode = types.item(j);
// 判断该子节点是否为元素节点
// getNodeType()方法返回节点类型,如果当前节点类型是==ELEMENT_NODE()方法返回元素节点的类型,.TEXT_NODE方法是返回文本节点
if (typeNode.getNodeType() == Node.ELEMENT_NODE) {
Element typeEle = (Element) typeNode;
System.out.println("\t" + typeEle.getAttribute("name"));
}
}
}
}
// 为XML文件添加元素
public void addEle() {
//创建一个<Brand>节点元素
Element brand = document.createElement("Brand");
//为元素节点添加属性及属性值
brand.setAttribute("name", "三星");
// <Type name="NOTE2"/>
Element type = document.createElement("Type");
type.setAttribute("name", "NOTE2");
//将Type作为Brand的子元素
brand.appendChild(type);
//先找到PhoneInfo元素节点再将Brand放到第一个PhoneInfo中去在将brand添加到PhoneInfo作为子节点
document.getElementsByTagName("PhoneInfo").item(0).appendChild(brand);
saveXML("收藏信息.xml");//调用saveXML方法时候可以通过传参的形式来确定传入的是原来的XML还是重新创建一个
}
//保存XML文件让document对象这棵树在内存里的变化保存到文件中去(需要借助转化器:源(最新的DOM树)---》目的地(XML文件),借助以输出流的形式)
public void saveXML(String path) {
//转化器工厂
TransformerFactory factory=TransformerFactory.newInstance();
//对修改的文件进行格式设置
factory.setAttribute("indent-number", 4);//首行缩进4
try {
//转化器
Transformer transformer=factory.newTransformer();
//指定转化格式
//transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");//设置转化之后的属性怕乱码保证XML与JAVA都是是UTF-8就不用再设置
transformer.setOutputProperty(OutputKeys.INDENT, "YES");//允许缩进
//源(最新的DOM树)---》目的地(XML文件)
DOMSource source=new DOMSource(document);//将最新的document树转化成domsource类型作为参数传给转化器对象的方法
//用StreamResult输出流将字节流包装成字符流
OutputStream out=new FileOutputStream(path);
StreamResult result=new StreamResult(new OutputStreamWriter(out));//另一种设置转化之后的属性方法在out后面加入,"GB2312"
transformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
//修改元素,给每个brand元素节点增加一个属性id
public void updateEle() {
//获取所有的brand
NodeList brands=document.getElementsByTagName("Brand");
for(int i=0;i<brands.getLength();i++) {
Node brand=brands.item(i);//拿到每一个brand节点
Element brandEle=(Element)brand;//将节点类型转化成元素类型的节点
brandEle.setAttribute("id", i+"");
}
saveXML("收藏信息.xml");
}
//删除 华为手机
public void deleteEle() {
//获取所有的Brand
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("华为")) {//找出是华为手机的bread节点
brandEle.getParentNode().removeChild(brandEle);//拿到父节点在删除子节点元素
}
}
}
public static void main(String[] args) {
ParseXMLDemo pd = new ParseXMLDemo();
pd.getDom();
pd.deleteEle();
pd.updateEle();
pd.addEle();
pd.showInfo();
}
}
6.DOM4解析
1.DOM4解析比DOM解析更加方便,少去很多复杂的要求,代码量相对会少一点
2.DOM4解析需要导入DOM4的架包来执行其中特殊的方法和类,导入步骤:
a.将dom4j复制粘贴到lib文件夹下,lib文件夹在NEW选项下的FOLDER创建
b.build Path选项下后面三个选项都可以导入,三种方法,选择包的所在路径就行。
3.
package xml4;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
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 Test {
private Document document;
//获得document对象
public void loadDocument() {
SAXReader saxReader=new SAXReader();//类似于得到一个解析器对象
try {
document=saxReader.read(new File("收藏信息.xml"));
} catch (DocumentException e) {
e.printStackTrace();
}
}
//显示手机的品牌及型号
public void showPhoneInfo() {
//使用getRootElement方法获得XML根节点,再讲节点进行转化为元素节点类型
Element root=document.getRootElement();
//获取所有<Brand>,除了可以用while循环以外还可以用for循环使用更简单一些
Iterator eleBrands=root.elementIterator();//用了迭代器返回成所有Brand一个集合
while(eleBrands.hasNext()) {//判断有没有下个元素
Element brand=(Element)eleBrands.next();//将迭代器集合进行遍历出每一个Object类型
System.out.println(brand.attributeValue("name"));//attributeValue方法是获得属性值
Iterator eleTypes=brand.elementIterator();//得到brand元素节点里面所有的子节点集合的对应(迭代器)
while(eleTypes.hasNext()) {
Element type=(Element)eleTypes.next();
System.out.println("\t"+type.attributeValue("name"));//获得型号
}
}
}
//修改节点
public void updatePhone() {
Element root=document.getRootElement();//获取根元素节点
Iterator eleBrands=root.elementIterator();//从根元素节点中提取出所有的迭代器对应的子元素集合
int id=0;//属性声明
while(eleBrands.hasNext()) {
Element brand=(Element)eleBrands.next();//遍历迭代器出每一个brand
id++;//给每个元素节点自动增加1
brand.addAttribute("id", id+"");//给brand节点添加属性
}
saveXml("newInfo.xml");
}
//删除节点
public void deletePhone() {
Element root=document.getRootElement();
Iterator eleBrands=root.elementIterator();
while(eleBrands.hasNext()){
Element brand=(Element)eleBrands.next();
if(brand.attributeValue("name").equals("三星")) {//判断如果name属性的有等于三星的
brand.getParent().remove(brand);//找到上一级节点删除此节点
}
}
saveXml("newInfo.xml");
}
//增加新的手机品牌信息
public void addNewPhone() {
//获得XML根元素
Element root=document.getRootElement();
//使用addElement方法创建指定根元素下的<Brand>元素节点
Element elBrand=root.addElement("Brand");
//给添加的元素增加属性
elBrand.addAttribute("name", "华为");
//创建元素节点下的子元素
Element elType=elBrand.addElement("Type");
//给元素节点添加属性
elType.addAttribute("name", "荣耀8");
saveXml("newInfo.xml");
}
//使修改后的DOM树保存修改到XML文件
public void saveXml(String path) {
OutputFormat format=OutputFormat.createPrettyPrint();//创建一个转化器输出一个漂亮的带有指定格式
//不纯在中文编码格式可以省略format.setEncoding("UTF-8");
XMLWriter writer=null;
try {
//得到一个往文件里写的字符类型输出流
writer =new XMLWriter(new OutputStreamWriter(new FileOutputStream(path)),format);//可以在path后面加入跟XML一样的编码格式
writer.write(document);//将doM树写出去
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
writer.close();//关闭资源
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Test domDemo=new Test();
domDemo.loadDocument();
domDemo.addNewPhone();
domDemo.updatePhone();
domDemo.deletePhone();
domDemo.showPhoneInfo();
}
}