一、XML介绍
XML的使用场景:(1)XML是用来传输和存储数据的。(2)XML 多用在框架的配置文件中。(3)XML 大多平台都支持,所以可以实现跨平台数据传输。
语法格式:<元素名 属性名=”属性值”>文本内容</元素名>
(1)前后元素名相同, 元素名自定义。(2)每个元素可以有0到多个属性,属性名自定义。(3)文本内容表示文字。(4)支持嵌套结构。(5)结束时元素名前有 /。
语法要求:(1)元素正确嵌套(2)XML文件的第一行必须是xml声明(3)只能有一个根节点(4)严格区分大小写(5)结束标签必须包含/(6)属性值的设置必须被""包围起来(7)XML认为换行标记也属于文本节点(8)<!-- -->
注释。有的非官方资料认为这是注释节点。
实体符号:
转义标签:< ! [ CDATA [ 要显示的字符 ] ] >
<?xml version="1.0" encoding="utf-8" ?><!--实例-->
<products>
<product>
<id>p001</id>
<name>蜘蛛王皮鞋</name>
<price>268</price>
<color>黑色</color>
<size>42</size>
<num>500</num>
</product>
<product>
<id>p002</id>
<name>ThinkPad x240</name>
<price>5678</price>
<color>黑色</color>
<size>12</size>
<num>50</num>
</product>
<product>
<id>p003</id>
<name>WD移动硬盘</name>
<price>568</price>
<color>黑色</color>
<size>5</size>
<num>1000</num>
</product>
</products>
二、DTD
介绍:DTD(Document Type Definition)文档类型定义。即约束XML文件中可以包含哪些元素、哪些属性、及元素个数和元素之间的关系和元素的顺序。在包含DTD的XML文件中,如果XML内容不满足DTD要求,会提示错误。
分类:DTD的三种分类:(1)内部DTD(2)外部DTD(3)公共DTD
内部DTD
<?xml version="1.0" encoding="UTF-8" ?>
<!--
!DOCTYPE:声明文档的类型,固定值
students:自定义根标签名
[]:自定义子标签
!ELEMENT:声明标签
students:标签名
(student):子标签
(student):有且只能有一个
(student?):至多一个
(student+):至少一个
(student*):任意个
students (student):students标签中有student子标签
student (name,age,sex):student标签中有name,age,sex子标签
使用子标签时顺序必须和指定一致
#PCDATA:字符串类型的值,没有子标签了
name (#PCDATA):name标签中为字符串值
!ATTLIST;声明属性
student:为哪个标签指定属性
id:自定义属性名
CDATA:属性控制,固定
#REQUIRED:必须有
#IMPLIED:可选择
#FIXED:固定值
#FIXED "18":固定值为18
-->
<!DOCTYPE students[
<!ELEMENT students (student*)>
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student id CDATA #REQUIRED>
<!ATTLIST name class CDATA #IMPLIED>
<!ATTLIST age abc CDATA #FIXED "18">
]>
<students>
<student id="1">
<name>chen</name>
<age>18</age>
<sex>nan</sex>
</student>
</students>
外部DTD
a.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--
从自己的本地引入
SYSTEM:固定值
"a.dtd":引入外部DTD文件的地址
-->
<!DOCTYPE students SYSTEM "a.dtd">
<students>
<student id="1">
<name></name>
<age></age>
<sex></sex>
</student>
</students>
a.dtd文件
<!ELEMENT students (student*)>
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student id CDATA #REQUIRED>
<!ATTLIST name class CDATA #IMPLIED>
<!ATTLIST age abc CDATA #FIXED "18">
公共DTD
语法:<!DOCTYPE 根元素名 PUBLIC "DTD标识名" "公用的DTD的URI">
三、XSD
XSD(XML Schema Definition )XML模式定义。
属于DTD的升级版。完美的解决了DTD使用时不易扩展问题,并且提供了更强大功能。
teacher.xsd
<!--
xs:schema : 自定义名字:schema固定
xmlns:xs : xmlns固定:自定义名字必须与前面的名字一致
xs:element : 定义标签
name="teachers" : 自定义标签名
ref="teacher" : 引用其他标签
maxOccurs="2" : 该标签至多2个,至少1个
type="xs:string" : 指定标签中文本内容的类型
xs:complexType : 定义复杂类型,其中可以指定子标签的使用顺序,属性值
xs:sequence : 指定子标签的顺序
xs:attribute : 指定标签中的属性
name="id" : 指定id为属性名
defult="abc" : 为属性设置默认值为abc
use : 指定属性是否可必要
required : 必要的
optional : 可选择的
prohibited : 禁止的
fixed="asb" : 为属性设置固定值
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="teachers">
<xs:complexType>
<xs:sequence>
<xs:element ref="teacher" maxOccurs="2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="teacher">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:integer"/>
<xs:element name="sex" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" use="required" fixed="asd"/>
</xs:complexType>
</xs:element>
</xs:schema>
teacher.xml
<?xml version="1.0" encoding="UTF-8" ?>
<teachers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="teacher.xsd">
<teacher id="asd">
<name>aa</name>
<age>12</age>
<sex>sac</sex>
</teacher>
</teachers>
四、XML解析
分类:在Java中提供了两种XML解析方式:DOM、SAX。
DOM解析:Document Object Model 文档对象模型。把XML文件一次性加载到内存中,并转换为树状模型。然后一个节点一个节点的解析,这种解析方式效率较高,但是比较消耗内存,适用于小型XML文档。
SAX解析:Simple API for XML是基于事件的解析,它是为了解决DOM解析的资源耗费而出现的。SAX在解析一份XML文档时,会依次出发文档开始、元素开始、元素结束、文档结束等事件,应用程序通过监听解析过程中所触发的事件即可获取XML文档的内容。该方式不需要事先调入整个文档,优势是占用资源少,内存消耗小,一般在解析数据量较大的文档是采用该方式。
五、DOM
使用DOM解析XML
package com.java.test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
public class TestDom {
public static void main(String[] args) throws Exception {
parseXML("teacher.xml");
}
public static void parseXML(String path) throws Exception{
//获取文档构建器工厂
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//根据文档构建器工厂获取文档构建器
DocumentBuilder db = dbf.newDocumentBuilder();
//使用文档构造器解析xml文件,将xml解析出的内容存储到Document对象中
Document document = db.parse(path);
//根据标签名获取标签结点集合
NodeList teachers = document.getElementsByTagName("teachers");
//获取根节点
Node root = teachers.item(0);
//获取结点名
System.out.println("根节点: " + root.getNodeName());
//获取根节点的子节点集合
NodeList childNodes = root.getChildNodes();
//遍历集合获取每一个节点
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
//判断节点类型为元素节点
if (item.getNodeType() == Node.ELEMENT_NODE){
System.out.println(" 子节点: "+item.getNodeName());
NodeList childNodes1 = item.getChildNodes();
for (int j = 0; j < childNodes1.getLength(); j++) {
Node item1 = childNodes1.item(j);
if(item1.getNodeType() == Node.ELEMENT_NODE){
//获取该节点的文本内容
System.out.println(" 子节点: " +item1.getNodeName()+" "+item1.getTextContent());
}
}
}
}
}
}
运行结果
使用DOM创建XML
package com.java.test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
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 java.io.FileOutputStream;
public class TestDom {
public static void main(String[] args) throws Exception {
//parseXML("teacher.xml");
createXML("person.xml");
}
//使用DOM创建XML
public static void createXML(String path) throws Exception {
//创建文档构建器工厂
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//根据文档构建器工厂获取文档构建器
DocumentBuilder db = dbf.newDocumentBuilder();
//根据文档构建器创建Document文档对象
Document document = db.newDocument();
//创建标签
Element root = document.createElement("persons");
Element person = document.createElement("person");
//为person标签设置属性及属性名
person.setAttribute("id","per");
Element name = document.createElement("name");
//设置文本内容
name.setTextContent("chen");
Element age = document.createElement("age");
age.setTextContent("18");
//指定标签之间的关系
person.appendChild(name);
person.appendChild(age);
root.appendChild(person);
//将根节点添加到文档中
document.appendChild(root);
//获取document转换为xml的转换器工厂
TransformerFactory tf = TransformerFactory.newInstance();
//根据转化器工厂获取转换器
Transformer transformer = tf.newTransformer();
//格式化
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","2");
//将document转换为xml,将xml输出到指定位置
transformer.transform(new DOMSource(document),new StreamResult(new FileOutputStream(path)));
}
}
六、SAX
使用SAX解析XML
package com.java.test;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.FileInputStream;
public class Main {
public static void main(String[] args) throws Exception {
//获取SAX解析器工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
//根据解析器工厂获取解析器
SAXParser sp = spf.newSAXParser();
//将解析xml的过程进行了封装,解析对应结点是,自动调用相关的方法
sp.parse(new FileInputStream("teacher.xml"),new MyHandler());
}
static class MyHandler extends DefaultHandler {
@Override//开始解析文档时,自动调用
public void startDocument() throws SAXException {
System.out.println("文档开始解析");
}
@Override//解析开始标签时,自动调用
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println("解析开始标签:"+qName);
}
@Override//解析文本时,自动调用
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println(new String(ch,start,length));
}
@Override//解析结束标签时,自动调用
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("解析结束标签:"+qName);
}
@Override//结束解析时,自动调用
public void endDocument() throws SAXException {
System.out.println("文档解析结束");
}
}
}
使用SAX创建XML
package com.java.test;
import org.xml.sax.helpers.AttributesImpl;
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 java.io.FileWriter;
public class TestSAXCreateXML {
public static void main(String[] args) throws Exception {
//获取SAX转换器工厂
SAXTransformerFactory stf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
//根据转换器工厂获取转换器执行器
TransformerHandler th = stf.newTransformerHandler();
//获取转换器
Transformer transformer = th.getTransformer();
//格式化
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
//将转换后的内容输出到该文件
th.setResult(new StreamResult(new FileWriter("phone.xml")));
//开始文档
th.startDocument();
//开始标签
th.startElement(null, null, "phones", null);
//设置属性
AttributesImpl attributes = new AttributesImpl();
attributes.addAttribute(null, null, "id", "String", "iph");
//开始标签时将属性放入到标签中
th.startElement(null,null,"phone",attributes);
th.startElement(null,null,"name",null);
//设置文本内容
char[] chars = "chen".toCharArray();
th.characters(chars,0,chars.length);
th.endElement(null,null,"name");
th.startElement(null,null,"age",null);
char[] chars1 = "18".toCharArray();
th.characters(chars1,0,chars1.length);
th.endElement(null, null, "age");
th.endElement(null, null, "phone");
th.endElement(null, null, "phones");
th.endDocument();
}
}