XML

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());
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值