XML的概念和体系
概念
XML:可扩展的标记语言
没有预定标签,需要自定义标签
特点
XML数据以纯文本格式存储
实现不同应用程序之间的数据通信
实现不同平台的数据通信
实现不同平台的数据共享
使用XML将不同的程序、不同的平台之间联系起来
作用
数据存储和数据传输
XML和HTML的区别
XML主要作用是数据存储和传输
HTML主要是用来显示数据
一个标准的XML文档
在Eclipse的项目下Ctrl+N新建输入XML选择新建XML FILE
<?xml version="1.0" encoding="UTF-8"?>
<!-- 一个标准的XML -->
<users>
<user>
<name>xjion-lqimi</name>
<age>20</age>
<gender>女</gender>
<hobit>handsome</hobit>
</user>
</users>
XML文件的体系
XHTML 可扩展标识语言
WSDL Web Services Description Language 网络服务描述语言,这种文档可描述某个 Web service
WAP 和 WML 手持设备的标记语言
RSS( 广 泛 用 于 网 上 新 闻 频 道 ) : Really Simple Syndication 简易信息聚合,使用 RSS 订阅能更快地获取 信息,网站提供 RSS 输出,有利于让用户获取网站内容 的最新更新
RDF 和 OWL: 重要的语义网技术语义网是为资产管理、 企业整合及网络数据的共享和重用提供的一个框架。
SMIL 同步多媒体集成语言,它是由万维网联盟规定的多 媒体操纵语言。最新的 SMIL 版本是 2001 年 8 月推出的 SMIL 2.0 版本,它通过时序排列对声音、影像、文字及图 形文件进行顺序安排,然后将这些媒体表现看起来是同步 的.
XML的基本语法
基本语法
(1)有且只有一个根元素
(2)XML文档声明必须放在文档的第一行
(3)所有标签必须成对出现
(4)XML的标签严格区分大小写
(5)XML必须正确嵌套
(6)XML中的属性值必须加引号
(7)XML中,一些特殊字符需要使用“实体”
(8)XML中可以应用适当的注释
元素
XML元素指的是开始标签到结束标签的部分
一个元素中可以包含
(1)其他元素
(2)文本
(3)属性
(4)以上的混合
命名规则
(1)名称可以包含字母、数字及其他字符
(2)名称不能以数字或者标点符号开始
(3)名称不能以字母xml开始
(4)名称不能包含空格
DTD验证
新建一个DTD文档
<?xml version="1.0" encoding="UTF-8"?>
<!--这是一个DTD文件 ELEMENT元素 Books(里面是必须有的元素,|代表或)+代表别的-->
<!ELEMENT Books (Book|Book1|Book2)+>
<!ELEMENT Book (name,author,price,publishers,color)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ELEMENT publishers (#PCDATA)>
<!ELEMENT color (#PCDATA)>
<!ATTLIST color color CDATA #FIXED> -->
新建一个XML文档
<?xml version="1.0" encoding="utf-8"?>
<!-- 导入DTD文档 -->
<!DOCTYPE Books SYSTEM "Books.dtd">
<Books>
<!-- Book标签里可以写对于这个标签 来说,不重要的属性 -->
<!-- 必须有的属性需要写在标签里面 -->
<Book color="蓝色">
<name>代码量与发量的反比例</name>
<author>xjion</author>
<price>18888¥</price>
<publishers>社会出版</publishers>
</Book>
<Book color="红色">
<name>ctrl</name>
<author>蔡某某</author>
<price>998$</price>
<publishers>社会出版</publishers>
</Book>
</Books>
PCDATA的意思是被解析的字符数据
CDATA不应由XML解析器进行解析的文本数据
使用DTD的局限性
(1)DTD不遵守XML语法
(2)DTD数据类型有限
(3)DTD不可扩展
(4)DTD不支持命名空间
内部文档声明
语法:
<!DOCTYPE 根元素 [元素声明]>
元素:<!ELEMENT 元素名称 (元素内容)>
+:1-n ?:0-1 *:n |:或者
属性:<!ATTLIST 元素名称 属性名称 属性类型 默认值>
#REQUIRED 必需的
#IMPLIED 不是必需的
#FIXED 固定的
外部文档声明
语法:
<!DOCTYPE 根元素 SYSTEM "文件名">
DOM解析
DOM解析(官方)
优点:
1、形成了树结构,有助于更好的理解、掌握,且代码容易编写。
2、解析过程中,树结构保存在内存中,方便修改。
缺点:
1、由于文件是一次性读取,所以对内存的耗费比较大。
2、如果XML文件比较大,容易影响解析性能且可能会造成内存溢出。
package cn.xjion.pro13;
import java.util.Scanner;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
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.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* XML DOM解析
* @author xjion
*
*/
public class TestDOM {
public static void main(String[] args) throws Exception {
//通过单例创建dom工厂实例
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
//通过工厂创建documentBuilder实例
DocumentBuilder db = dbFactory.newDocumentBuilder();
createXML(db);
//增删查改
queryXML(db);
}
private static void queryXML(DocumentBuilder db) throws Exception{
// TODO Auto-generated method stub
//获取doc文档节点
Document doc = db.parse("books.xml");
//获取doc文档节点下的所有子节点
NodeList nodes = doc.getChildNodes();
//创建可以递归的查询方法
query(nodes);
}
/*
* NodeType
* 1: 元素节点
* 2: 属性节点
* 3: 文本节点
*
*/
private static void query(NodeList nodes) {
// TODO Auto-generated method stub
//判断nodes不等于null
if (nodes!=null) {
for (int i = 0; i<nodes.getLength();i++) {
//获取当前下标节点
Node node = nodes.item(i);
//判断当前节点的子节点是否是文本节点
if (node.getChildNodes().item(0).getNodeType()==3) {
//打印当前节点名和文本节点
System.out.println(node.getNodeName()+":"+node.getTextContent());
}else {
//打印当前节点
System.out.println(node.getNodeName());
}
//获取当前节点所有属性节点
NamedNodeMap map = node.getAttributes();
//遍历属性集合
if (map!=null&&map.getLength()>0) {
//遍历属性集合
for (int j = 0; j < map.getLength(); j++) {
//获取集合中属性节点
Node att = map.item(j);
//判断att不为null
if (att!=null) {
//开始拼接属性信息
if (j==0) {
//打印开始节点信息
System.out.print("Attribute:[");
}
//打印属性节点信息
System.out.print(att.getNodeName()+(att.getNodeValue()==null?"":":"+att.getNodeValue()+"\t"));
//结尾拼接
if (j==map.getLength()-1) {
System.out.println("]");
}
}
}
}
//判断子节点是元素节点才会获取子节点递归遍历
if (node.getChildNodes().item(0).getNodeType()==1) {
query(node.getChildNodes());
}
}
}
}
//创建文件
private static void createXML(DocumentBuilder db) throws Exception {
// TODO Auto-generated method stub
//创建新的document文档
Document doc = db.newDocument();
//创建根节点
Element root = doc.createElement("books");
//创建子节点
Element book1 = doc.createElement("book");
Element book2 = doc.createElement("book");
//book有固定 的子节点name,author,price,publishers
Element name1 = doc.createElement("name");
Element author1 = doc.createElement("author");
Element price1 = doc.createElement("price");
Element publishers1 = doc.createElement("publishers");
Element name2 = doc.createElement("name");
Element author2 = doc.createElement("author");
Element price2 = doc.createElement("price");
Element publishers2 = doc.createElement("publishers");
//添加文本节点
name1.setTextContent("java从入门到成神");
author1.setTextContent("xjion");
price1.setTextContent("250CNY");
publishers1.setTextContent("ctrl");
name2.setTextContent("mysql从入门到删库");
author2.setTextContent("蔡");
price2.setTextContent("250CNY");
publishers2.setTextContent("ctrl");
//添加属性
book1.setAttribute("color","yellow");
book2.setAttribute("color","blue");
//把子节点添加到相对应的节点中
book1.appendChild(name1);
book1.appendChild(author1);
book1.appendChild(price1);
book1.appendChild(publishers1);
book2.appendChild(name2);
book2.appendChild(author2);
book2.appendChild(price2);
book2.appendChild(publishers2);
root.appendChild(book1);
root.appendChild(book2);
doc.appendChild(root);
//用户输入文件名
Scanner sc = new Scanner(System.in);
System.out.println("请输入xml的文件名:");
String str = sc.next();
//更新xml文件
upXML(doc,str+".xml");
}
private static void upXML(Document doc, String string) throws Exception {
// TODO Auto-generated method stub
//创建transformer工厂
TransformerFactory tfFactory = TransformerFactory.newInstance();
//创建transformer实例
Transformer tf = tfFactory.newTransformer();
//设置输出的字符集
tf.setOutputProperty(OutputKeys.ENCODING,"utf-8");
//设置节点源
DOMSource source = new DOMSource(doc);
//设置文件名
StreamResult result = new StreamResult(string);
//把doc节点转换成xml文件信息
tf.transform(source,result);
System.out.println("创建完成");
}
}
SAX解析
SAX解析
优点:
1、采用事件驱动模式,对内存耗费比较小。
2、适用于只处理XML文件中的数据时。
缺点:
1、编码比较麻烦。
2、很难同时访问XML文件中的多处不同数据。
package cn.xjion.pro13;
public class Book {
// 属性
private String Color;
private String name;
private String author;
private String price;
private String publishers;
// 构造器
public Book() {
super();
// TODO Auto-generated constructor stub
}
// get,set方法
public String getColor() {
return Color;
}
public void setColor(String color) {
Color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getPublishers() {
return publishers;
}
public void setPublishers(String publishers) {
this.publishers = publishers;
}
// 重写toString
@Override
public String toString() {
return "Book [Attribute:'Color'='" + Color + "' Nodes: name=" + name + ", author=" + author + ", price=" + price + ", publishers="
+ publishers + "]";
}
}
package cn.xjion.pro13;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class BookHandler extends DefaultHandler {
//声明集合,存储查询的全部数据,传回查询处
private List<Book> list = null;
//声明实体类
private Book book = null;
//当前标签名
private String currentTag = null;
//当前传入标签名
private String nodeName = null;
// 构造器
public BookHandler(String string) {
// TODO Auto-generated constructor stub
this.nodeName = string;
}
// get方法
public List<Book> getList() {
return list;
}
// 下面的5个是重写父类方法
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
// 创建Docment对象就新建List容器
super.startDocument();
list = new ArrayList<>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
// 如果传入的对象名字与当前名字相同就创建书籍对象
if (qName.equals(nodeName)) {
book = new Book();
}
//添加属性
if (attributes!=null&&attributes.getValue("color")!=null) {
book.setColor(attributes.getValue("color"));
}
// 把传入标签名赋值给当前标签名
currentTag = qName;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
// 创建一个字符串对象接收传进来的数组对象
String str = new String(ch,start,length) ;
// 如果这个字符串不为空切和某个标签名相同就传入标签里面
if (!"".equals(str.trim())&&"name".equals(currentTag)) {
book.setName(str);
}else if (!"".equals(str.trim())&&"author".equals(currentTag)) {
book.setAuthor(str);
}else if (!"".equals(str.trim())&&"price".equals(currentTag)) {
book.setPrice(str);
}else if (!"".equals(str.trim())&&"publishers".equals(currentTag)) {
book.setPublishers(str);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
// 标签名相同就传入容器,关闭对象
if (qName.equals(nodeName)) {
list.add(book);
}
}
// 关闭Docment对象
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
}
}
package cn.xjion.pro13;
import java.io.File;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.xml.sax.helpers.AttributesImpl;
public class TestSAX_XML {
public static void main(String[] args) throws Exception {
// createXML();
queryXML();
}
private static void queryXML() throws Exception {
// TODO Auto-generated method stub
//创建SAXParser工厂实例
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//创建SAXParser实例
SAXParser parser= saxParserFactory.newSAXParser();
//创建管理者
BookHandler hand = new BookHandler("book");
//给解析器传入具体文件以及管理者
parser.parse("books.xml",hand);
List<Book> list = hand.getList();
for (Book book : list) {
System.out.println(book);
}
}
private static void createXML() throws Exception {
// TODO Auto-generated method stub
//创建SAXtransformer工厂实例
SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
//创建transformer管理者实例
TransformerHandler th = saxTransformerFactory.newTransformerHandler();
//创建转换实例
Transformer tf = th.getTransformer();
//设置字符集
tf.setOutputProperty(OutputKeys.ENCODING,"utf-8");
//换行
tf.setOutputProperty(OutputKeys.INDENT,"yes");
//创建文件源
File file = new File("books.xml");
if (file!=null&&!file.exists()) {
file.createNewFile();
}
//设置需要输出的文件源
StreamResult result = new StreamResult(file);
//给管理者传入需要输出的文件源
th.setResult(result);
//创建属性对象
AttributesImpl attr = new AttributesImpl();
//开启doc文档节点
th.startDocument();
//开启根节点
th.startElement("","","books",null);
//设置属性
attr.addAttribute("","","color","","yellow");
//开启book节点,传入属性对象
th.startElement("","","book",attr);
attr.clear();
//开启name节点
th.startElement("","","name",null);
//设置文本节点
String str = "java从入门到成神";
th.characters(str.toCharArray(),0,str.length());
//关闭name节点
th.endElement("","","name");
//开启author节点
th.startElement("","","author",null);
//设置文本节点
str = "xjion";
th.characters(str.toCharArray(),0,str.length());
//关闭author节点
th.endElement("","","author");
//开启price节点
th.startElement("","","price",null);
//设置文本节点
str = "250CNY";
th.characters(str.toCharArray(),0,str.length());
//关闭author节点
th.endElement("","","price");
//开启publishers节点
th.startElement("","","publishers",null);
//设置文本节点
str = "cdsxt";
th.characters(str.toCharArray(),0,str.length());
//关闭publishers节点
th.endElement("","","publishers");
//关闭book节点
th.endElement("","","book");
//关闭books节点
th.endElement("","","books");
//关闭doc节点
th.endDocument();
System.out.println("sax创建完成");
}
}
JDOM解析
JDOM是一种解析XML的Java工具包,它基于树型结构,利用纯Java的技术对XML文档实现解析。所以只适合于Java语言。
特征:
1、仅使用具体类,而不使用接口。
2、API大量使用了Collections类。
步骤:
(1)创建一个SAXBuilder对象
(2)调用build方法,得到Document对象(通过IO流)
(3)获取根节点
(4)获取根节点的直接子节点的集合
(5)遍历集合
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
public class TestJDOM {
public static void main(String[] args) throws FileNotFoundException, JDOMException, IOException {
//(1)创建一个SAXBuilder对象
SAXBuilder sb = new SAXBuilder();
//(2)调用build方法,得到Document对象(通过IO流)
Document doc = sb.build(new FileInputStream("book.xml"));
//(3)获取根节点
Element root = doc.getRootElement();
//(4)获取根节点的直接子节点的集合
List<Element> bookEle = root.getChildren();
//(5)遍历集合,得到book的每一个子节点(子元素)
for (int i = 0;i < bookEle.size();i++) {
Element book = bookEle.get(i);
//得到属性集合
List<Attribute> attList = book.getAttributes();
//遍历属性的集合得到每一个属性
for (Attribute attr : attList) {
System.out.println(attr.getName()+"\t"+attr.getValue());
}
}
//得到每一个子节点
System.out.println("\n----------------------");
for(int i = 0;i<bookEle.size();i++) {
Element book = bookEle.get(i);//得到每一个book节点
List<Element> subBook = book.getChildren();
//遍历每一个节点,获取节点名称节点值
for (Element ele : subBook) {
System.out.println(ele.getName()+"\t"+ele.getValue());
}
System.out.println("================================");
}
}
}
DOM4J
DOM4J是一个Java的XML API,是JDOM的升级品,用来读写XML文件的。
特征:
1、JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能。
2、它使用接口和抽象基本类方法。
3、具有性能优异、灵活性好、功能强大和极端易用的特点。
4、是一个开放源码的文件
步骤:
(1)创建SAXReader对象
(2)调用read方法
(3)获取根元素
(4)通过迭代器遍历直接节点
public class Book {
private String name;
private String author;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Book(String name, String author, double price) {
super();
this.name = name;
this.author = author;
this.price = price;
}
public Book() {
super();
}
}
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.java.entity.Book;
public class TestDOM4J {
public static void main(String[] args) throws DocumentException {
//(1)创建SAXReader对象
SAXReader reader = new SAXReader();
//(2)调用read方法
Document doc = reader.read(new File("book.xml"));
//(3)获取根元素
Element root = doc.getRootElement();
//(4)通过迭代器遍历直接节点
for(Iterator<Element> iteBook = root.elementIterator();iteBook.hasNext();) {
Element bookEle = iteBook.next();
//System.out.println(bookEle.getName());
//得到book的属性
for(Iterator<Attribute> iteAtt = bookEle.attributeIterator();iteAtt.hasNext();) {
Attribute att = iteAtt.next();
System.out.println(att.getName()+"\t"+att.getText());
}
}
List<Book> bookList = new ArrayList<Book>();
System.out.println("\n-------------------");
for(Iterator<Element> iteBook = root.elementIterator();iteBook.hasNext();) {
//创建Book对象
Book book = new Book();
Element bookEle = iteBook.next();//得到每一个book
//使用for循环继续遍历
for(Iterator<Element> subBookEle = bookEle.elementIterator();subBookEle.hasNext();) {
//得到每一个子元素
Element subEle = subBookEle.next();
System.out.println(subEle.getName()+"\t"+subEle.getText());
/**
* 封装成Book对象
*/
//获取节点的名称
String nodeName = subEle.getName();
//使用switch判断
switch (nodeName) {
case "name":
book.setName(subEle.getText());
break;
case "author":
book.setAuthor(subEle.getText());
break;
case "price":
book.setPrice(Double.parseDouble(subEle.getText()));
break;
}
}
//添加到集合中
bookList.add(book);
}
//遍历集合
System.out.println("\n遍历集合-----------------");
for(Book b:bookList) {
System.out.println(b.getName()+"\t"+b.getAuthor()+"\t"+b.getPrice());
}
}
}