XML介绍
XML 是一种标记语言,类似于HTML,XML是可扩展标记语言,严格区分大小写。
HTML是用来显示数据的。XML是用来存储和传输数据的,多用在框架的配置文件中,可实现跨平台数据传输。
HTML中的标签是定义好的,用户直接使用这些标签。XML标签没有被预定义,XML本身如果没有任何规范或约定的话,所有标签都是自定义的。
XML语法格式
<元素名 属性名="属性值">文本内容</元素名>
注意事项
1.严格区分大小写
2.元素名和属性名均自定义
3.前后元素名保持一致(包括大小写)
4.结束标签必须包含 /
5.属性值必须被 " " 包围
6.每个元素可以有0到多个属性
7.元素需正确嵌套
8.XML文件的第一行必须是xml声明
<?xml version="1.0" encoding="UTF-8"?> //文档头,声明版本和编码
9.只能有一个根节点
10.元素节点是标签,属性节点是属性(包含属性名和属性值),文本节点是标签之间的文本值。
11.XML认为换行标记也属于文本节点
特殊字符
实体符号
在XML中必须要写某些符号,但是写上会报错,这时需要使用实体符号。
特殊字符 | 字符实体 |
< | < |
> | > |
& | & |
' | ' |
" | " |
转义标签
在当前标签,需要存储的内容中包含许多特殊字符,全都转换为字符实体过于麻烦,这时可以使用转义标签。
转义标签:可将特殊字符转换为普通字符
<![CDATA[
> < >> & ;;; ::: ''' """
]]>
DTD
DTD是文档类型定义。
通过DTD约束XML文件中的元素、属性等,包括哪些元素、哪些属性、元素个数、元素之间的关系、元素顺序。
DTD缺点是,当对XML文件结构更新时,需要修改整个DTD文件,可扩展性较差。
DTD分类
内部DTD、外部DTD、公共DTD
内部DTD
直接在XML中编写DTD内容
<!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 test CDATA #IMPLIED>
<!ATTLIST age class CDATA #FIXED "18">
<!ATTLIST sex aa CDATA #REQUIRED bb CDATA #IMPLIED>
]>
<students>
<student id="">
<name></name>
<age></age>
<sex aa=""></sex>
</student>
</students>
!DOCTYPE:文档类型的声明,XML中的内容必须为声明中的内容
students:根标签的名称(自定义的)
[ ]:XML中可以有哪些标签和属性
!ELEMENT:定义元素(标签)
<!ELEMENT students (student)>:定义根标签中的子标签
1. (student):必须且仅有一个
2. (student?):可以有一个或者零个
3. (student+):可以有至少一个
4. (student*):可以有零到多个
<!ELEMENT students (name, age, sex)>:只能有name, age, sex,且顺序必须为指定的顺序
<!ELEMENT name (#PCDATA)>:name标签中为文本内容
<!ATTLIST 标签名 自定义属性名 CDATA #REQUIRED>
CDATA:属性控制
1.#REQUIRED:必须存在的(标签student中必须有属性id)
2.#IMPLIED:可选的(标签name中可以有属性test,也可以没有)
3.#FIXED "值":固定值(标签age中可以有属性class,也可以没有,但是如果有的话,属性值一定为18)
外部DTD(常用)
外部DTD是单独编写一个后缀为.dtd的文件,然后通过引入方式引入DTD。
<!-- dog.dtd -->
<!ELEMENT dogs (dog+) >
<!ELEMENT dog (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ATTLIST dog id CDATA #IMPLIED>
<?xml version="1.0" encoding="UTF-8" ?>
<!-- XML -->
<!DOCTYPE dogs SYSTEM "dog.dtd">
<dogs>
<dog>
<name></name>
<age></age>
</dog>
</dogs>
公共DTD
公共DTD是由一些开源组织编写的DTD,需要使用时按照要求的语法格式使用。
<!DOCTYPE 根元素 PUBLIC "DTD标识名" "公用DTD的URI">
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
XSD
XSD是XML模式定义,在DTD基础上解决了使用时不易扩展问题。
同一个XML文件只能引入DTD或XSD其中之一,不能同时引入。
XSD只能使用外部XSD,即创建后缀为.xsd的文件,通过引入方式引入XSD。
<!-- cat.xsd -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="cats">
<xs:complexType>
<xs:sequence>
<xs:element name="cat" maxOccurs="3">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="sex" type="xs:string"/>
<xs:element name="age" type="xs:int"/>
</xs:sequence>
<xs:attribute name="id" fixed="zs" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">:声明XSD约束
xs:自定义名称(前后需保持一致)
<xs:element name="cat" maxOccurs="3">
1.name:指定标签名为cat
2.maxOccurs:指定标签的个数上限
maxOccurs="3":标签个数最多为3个
maxOccurs="unbounded":标签个数无上限
<xs:complexType>:复杂类型,指定子标签、属性……
<xs:sequence>:指定有哪些子标签及其顺序
complexType和sequence搭配使用,通过复杂类型里具体的细节(顺序),控制cat标签中的子标签name,sex,age,后续指定子标签时必须按照这个顺序指定。
<xs:element name="age" type="xs:int"/>:指定age中存放的文本节点值类型为int
<xs:attribute name="id" default="zs" use="optional"/>属性(需要放在复杂类型里)
1.name:属性名,指定cat中属性的属性名为id
2.default="值":默认属性值
fixed="值":固定属性值
3.use 属性的状态
use="optional":可选(可有可无)
use="required":必须(一定要有)
use="prohibited":禁止(一定不能有)
<?xml version="1.0" encoding="UTF-8" ?>
<cats xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="cat.xsd">
<cat id="zs">
<name></name>
<sex>男</sex>
<age>0</age>
</cat>
</cats>
XML解析
JAVA中XML的两种解析方式分别为DOM和SAX。
解析的目的是拿出标签之间的值,而不是标签。
解析的是XML文件中的根节点及子节点,与DTD和XSD无关。
DOM
简介
DOM是文档对象模型,是将XML文件一次性加载到内存中并转换为树状模型,是将XML中的标签解析为元素节点对象。
这种方式效率高但是比较消耗内存,适用于小型XML文档。
解析器是基于工厂设计模式的,不需要自己创建解析器,基于工厂直接获取解析器。
获取到XML文档后,每个元素都是一个节点,只需要操作节点对象就可以。
在DOM解析时需要过滤掉换行。
DOM解析示例
(出现问题,转成文件类)
<?xml version="1.0" encoding="UTF-8" ?>
<!--
doggg.xml
-->
<!DOCTYPE dogs SYSTEM "dog.dtd">
<dogs>
<dog id="dog">
<name>旺财</name>
<age>10</age>
</dog>
<dog id="dog1">
<name>小花</name>
<age>0.5</age>
</dog>
public class DOMParseXML {
public static void parse(String path) throws Exception{
//1.创建文档构建器工厂
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//2.根据文档构建器工厂获取文档构建器
DocumentBuilder db = dbf.newDocumentBuilder();
//3.通过文档构建器解析XML
//Document document = db.parse(path);
File file = new File(path);
Document document = db.parse(file);
//4.获取根节点
NodeList dogs = document.getElementsByTagName("dogs");
Node root = dogs.item(0); //获取第一个节点
String nodeName = root.getNodeName(); //获取节点名
System.out.println("根节点名:"+nodeName);
//5.获取根节点的所有子节点
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) {
String textContent = item1.getTextContent(); //获取该元素节点的文本节点值
System.out.println(" 子节点名:" + item1.getNodeName()+" "+textContent);
}
}
}
}
}
}
public class TestDOMParse {
public static void main(String[] args) throws Exception {
//DOMParseXML.parse("doggg.xml");
DOMParseXML.parse("D:\\JAVA就业\\03.阶段3\\Day04\\源码\\Stage03_Day04\\doggg.xml");
}
}
使用DOM生成XML
DOM生成XML主要是创建节点
public class DOMCreateXML {
public static void create(String path) throws Exception{
//1.获取文档构建器工厂
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//2.根据文档构建器工厂获取文档构建器
DocumentBuilder db = dbf.newDocumentBuilder();
//3.通过文档构建器生成XML
Document document = db.newDocument(); //没有任何节点
//4.创建元素节点
Element root = document.createElement("rabbits");
Element rabbit = document.createElement("rabbit");
rabbit.setAttribute("id","小灰兔"); //属性
Element name= document.createElement("name");
name.setTextContent("兔子");
Element sex = document.createElement("sex");
sex.setTextContent("母");
Element age = document.createElement("age");
age.setTextContent("10");
Element addr = document.createElement("addr");
addr.setTextContent("海淀");
//5.指定元素节点之间的关系
rabbit.appendChild(name);
rabbit.appendChild(sex);
rabbit.appendChild(age);
rabbit.appendChild(addr);
root.appendChild(rabbit);
document.appendChild(root);
//设置为独立的xml
document.setXmlStandalone(true);
//6.创建转换器工厂
TransformerFactory tf = TransformerFactory.newInstance();
//根据转换器工厂获取转换器
Transformer t=tf.newTransformer();
//调整格式
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
//7.将document对象转换为XML并输出到指定的位置
/*
* 参数一:new DOMSource(document) -> 将document对象转换为XML
* 参数二:输出流
* */
t.transform(new DOMSource(document),new StreamResult(new FileOutputStream(path)));
}
}
public class TestDOMCreate {
public static void main(String[] args) throws Exception{
DOMCreateXML.create("rabbit.xml");
}
}
SAX解析
简介
SAX是基于事件的解析,事件驱动,边读边写。
应用程序通过监听解析过程中所触发的事件获取XML文档的内容。相当于封装好了解析的方法,使用时直接调取。
这种方式占用资源少,内存消耗小,解决了DOM解析的资源耗费,SAX适用于较大的XML文档。
在SAX解析时需要过滤掉换行。
SAX解析示例
public class SAXParseXML {
public static void parse(String path) throws Exception{
//1.创建SAX解析器工厂对象
SAXParserFactory spf=SAXParserFactory.newInstance();
//2.基于工厂获取解析器对象
SAXParser sp=spf.newSAXParser();
//3.使用解析器解析XML
sp.parse(new File(path), new MyHandler());
}
}
public class MyHandler extends DefaultHandler {
String name=null;
@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);
name=qName;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String s=new String(ch,start,length);
System.out.println(s);
}
@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("文档解析结束");
}
}
public class TestSAXParse {
public static void main(String[] args) throws Exception{
SAXParseXML.parse("D:\\JAVA就业\\03.阶段3\\Day04\\源码\\Stage03_Day04\\doggg.xml");
}
}
使用SAX生成XML
public class SAXCreateXML {
public static void create(String path) throws Exception{
//1.创建转换器工厂
SAXTransformerFactory stf=(SAXTransformerFactory)SAXTransformerFactory.newInstance();
//2.基于工厂获取转换器
TransformerHandler th=stf.newTransformerHandler();
Transformer tf = th.getTransformer();
//调整格式
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.setOutputProperty(OutputKeys.ENCODING, "utf-8");
tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
//3.将document对象转换为XML并输出到指定的位置
th.setResult(new StreamResult(new FileOutputStream(path)));
//4.创建元素节点
th.startElement(null, null, "students", null);
AttributesImpl attributes = new AttributesImpl();
attributes.addAttribute(null, null, "id", null, "aa");
th.startElement(null, null, "student", attributes);
th.startElement(null, null, "name", null);
char[] chars = "zs".toCharArray(); //toCharArray():将字符串对象中的字符转换为一个字符数组。
th.characters(chars, 0, chars.length);
th.endElement(null, null, "name");
th.startElement(null, null, "age", null);
char[] chars1 = "19".toCharArray();
th.characters(chars1, 0, chars1.length);
th.endElement(null, null, "age");
th.startElement(null, null, "sex", null);
char[] chars2 = "男".toCharArray();
th.characters(chars2, 0, chars2.length);
th.endElement(null, null, "sex");
th.endElement(null, null, "student");
th.endElement(null, null, "students");
th.endDocument();
}
}
public class TestSAXCreate {
public static void main(String[] args) throws Exception{
SAXCreateXML.create("student.xml");
}
}