-
XML概述
xml,extend markup language,可扩展标记语言。
html语言的问题(非常松散):
1)html的标签不分大小写 。
2)html的标签可以不匹配。
xml语法比html语法更加严谨:
1)xml的标签区分大小写的
2)xml的标签必须匹配
xml的作用:
1)描述带关系的数据结构,所以可以作为软件的配置文件
2)存储数据,所以可以作为“小型的数据库”
html
名称: 超文本标记语言
标签的定义: w3c固定的标签
作用: 负责网页的结构(展示)
xml
名称: 可扩展标记语言
标签的定义: 可以让开发者自定定义(扩展)
作用: (1)软件的配置文件(2)小型的“数据库”
1)软件的配置文件
.properties文件。格式: key=value key=value 没有的关系,不能描述数据的关系
xml文件格式:( xml可以描述包含与被包含)
<student>
<name>张三</name>
</student>
<student>
<name>李四</name>
</student>
(1) 作为软件的配置(最常见)
struts2, spring, hibernate 软件的半成品 + xml文件 tomcat服务器 ->xml文件
(2)“小型数据库”
存储到mysql数据库的数据,同样也可以存储到xml文件
-
XML语法
xml文档声明
第一行: <?xml version="1.0" encoding="GBK" standalone="yes"?>
version: 代表xml文件的版本 通常用1.0就可以了
encoding: 编码。解析器解析xml文件时的编码(中文).默认值是UTF-8
(浏览器内置了xml解析器,所以浏览器可以解析xml文件)
涉及xml文件的编码问题:
1)保存xml文件时的编码
2)文档声明的encoding
3)浏览器的设置编码
三个编码必须保持一致,这样才不会出现中文乱码问题!!!
standalone: 是否引用了文件
2)注释
<!-- xml注释 -->
3)标签,属性
命名规则:
区分大小写,例如,<P>
和<p>
是两个不同的标签。
不能以数字开头。
不能以xml(或XML、或Xml 等)开头。(执行是可以,是xml名称是xml语法的保留关键 词)
中间和开头不能包含空格。
名称中间不能包含冒号(:)。(冒号是名称空间的保留字符,不能用。比如:itcast:)
标签:
在一个xml文件中,有且仅有一个根标签
属性:
1)可以有多个属性,每个属性以name="值"形式存在
2)属性值必须使用引号包含,要么是单引号,要么是双引号,不能单双混用
3) 在同一个标签内不能出现两个同名属性
4)转义字符
< <
> >
空格
“ "
’ '
5)CDATA
语法:<![CDATA[ 内容 ]]>
作用:可以同时对CDATA的内容进行转义。
6)处理指令
作为html作用使用。
可以通知解析器忽略标签名内容,只保留标签体内容。
<?xml-stylesheet type="text/css" href="xmlcss.css"?>
在xmlcss.css中选择元素,设置样式。
-
XML约束之dtd
什么是良好的XML?
符合W3C制定的语法规范(也就是上面所提到的所有XML语法),我们就说这个XML是良好的XML。
什么是有效的XML?
符合约束规则,通过了用户自定义的DTD或者Schema校验的约束规则,我们就说这个XML是有效的XML。
使用(dtd约束和schema约束)约束xml,让其成为有效的xml。
dtd约束,语法比较简单,功能不够丰富(数据类型比较单一)struts2和hierbnate的xml约束就是使用dtd约束。
schema约束,为了替代dtd约束,语法相对强大,功能比较丰富(数据类型丰富,支持名称空间)spring的xml使用的是schema约束,tomcat的web.xml使用schema约束。
dtd约束
知识点链接:https://www.runoob.com/dtd/dtd-intro.html
dtd约束的导入方式
(1).内部导入
特点:dtd内容和xml内容放在一个文件。
(2).外部导入
本地外部导入:dtd文件保存在本地文件系统中
<!DOCTYPE 根元素 SYSTEM "文件名">
网络外部导入:dtd文件保存在互联网上
<!DOCTYPE 文档根结点 PUBLIC "DTD名称" "DTD文件的URL">
dtd语法
在一个 DTD 中,元素通过元素声明来进行声明。
声明一个元素
在 DTD 中,XML 元素通过元素声明来进行声明。元素声明使用下面的语法:
类别:(粗略控制,不想schema那么细致)
EMPTY:空元素
<!ELEMENT element-name EMPTY>
实例:
<!ELEMENT br EMPTY>
XML example:
<br />
PCDTAT:普通字符串(包括空,不包含子元素)
<!ELEMENT element-name (#PCDATA)>
实例:
<!ELEMENT from (#PCDATA)>
ANY:任意内容(包含子元素)
<!ELEMENT element-name ANY>
实例:
<!ELEMENT note ANY>
元素内容
顺序问题:(子元素1,子元素2…)一定从左到右依次出现,否则违反约束。
数量问题:
子元素1:有且仅出现一次。
子元素1+:至少出现一次。
子元素1?:出现0或1次。
子元素1*:出现0或多次。
约束属性:
在 DTD 中,属性通过 ATTLIST 声明来进行声明。
声明属性
属性声明使用下列语法:
<!ATTLIST element-name attribute-name attribute-type attribute-value>
DTD 实例:
<!ATTLIST payment type CDATA "check">
XML 实例:
<payment type="check" />
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
默认值:控制属性是否必须
#REQUIRED 属性值是必需的
#IMPLIED 属性不是必需的
#FIXED value 属性值是固定的(可以不写,一旦写了只能写固定值)
属性类型:
CDATA 值为字符数据 (character data,”001“)
(en1|en2|..) 此值是枚举列表中的一个值
ID 值为唯一的 id
IDREF 值为另外一个元素的 id
IDREFS 值为其他 id 的列表
NMTOKEN 值为合法的 XML 名称
NMTOKENS 值为合法的 XML 名称的列表
ENTITY 值是一个实体
ENTITIES 值是一个实体列表
NOTATION 此值是符号的名称
xml: 值是一个预定义的 XML 值
-
XML解析之DOM解析
xml解析:使用java代码去操作(包括改写)xml文件。
xml解析方式:
DOM解析:
XML DOM原理:xml文档被封装成不同的对象,通过这些对象操作xml文档。把xml文件封装成不同的对象(Document,Element,Attr,Text,Comment),通过对象操作xml文件。
特点:一次性把整个xml文档读入内存,然后组建成DOM树。占用比较大的内存。不太适合读大的文件,容易内存溢出。
面向对象编程方式。
SAX解析:
解析原理:读取一点,解析一点。占用内存非常小。适合读大文件。
基于事件驱动的。
DOM解析工具:
jaxp:sun公司的标准(老产品)。
jdom:开源组织的产品,在jaxp之上封装。
dom4j:是jdom的子产品,在jdom之上封装(更流行)。struts2内部使用的dom4j解析xml配置文件
iaxp工具的使用:
按照DOM原理使用jaxp解析xml文件
jaxp的api在jdk中 org.w3c.dom.*
读取开发步骤:
1.创建DocumentBuilderFactory实例
2.通过DocumentBuilderFactory实例创建DocumentBuilder
3.通过DocumentBuilder的parse方法读取xml文件,返回一个Document对象。
常用方法:
getElementsByTagName() 根据标签名查元素
getElementById()根据id查元素
getAttribute(“name”)根据属性查元素
getTextContent()根据文本内容查元素
NodeList:
getLength()获取节点的长度
item(index)根据下标找节点
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package gz.itcast.a_jaxp;
//目标:jaxp如何读取xml文件
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class DOM1 {
public DOM1() {
}
public static void main(String[] args) throws Exception {
//创建DocumentBuilderFactory实例
// Ctrl+2 松开 l
DocumentBuilderFactory factroy = DocumentBuilderFactory.newInstance();
//通过DocumentBuilderFactory实例创建DocumentBuilder
DocumentBuilder builder = factroy.newDocumentBuilder();
//通过DocumentBuilder的parse方法读取xml文件,返回一个Document对象。
Document doc = builder.parse("src/Locale.xml");
System.out.println(doc);
}
}
修改xml步骤
1.创建TransformerFactory实例。
2.通过TransformerFactory实例创建Transformer。
3.通过Transformer的transfer方法把Document写出xml文件。
createElement(“name”)创建元素
setAttribute(“name”,“value”)创建或修改元素的属性
removeAttribute(“name”)删除属性
setTextContent(“内容”)设置文本内容
案例:
package gz.itcast.a_jaxp;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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.Node;
import org.w3c.dom.NodeList;
public class DOM2 {
public DOM2() {
}
public static void main(String[] args) throws Exception {
//读取xml文件
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("src/Locale.xml");
test4(doc);
}
//遍历所有节点
public static void test1(Document doc) {
//得到根节点(Location)
Node root = doc.getElementsByTagName("Location").item(0);
getChildNodes(root);
}
//递归遍历子节点(只需要看元素节点 元素的节点类型Node.ELEMENT_NODE=1)
public static void getChildNodes(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out.println(node.getNodeName());
}
//得到当前节点的所有子节点
NodeList nList = node.getChildNodes();
//遍历
for(int i = 0; i < nList.getLength(); ++i) {
//得到每一个节点
Node n = nList.item(i);
//递归调用getChildNodes(),为了查询当前节点的子节点。
getChildNodes(n);
}
}
//查询某个节点 1.找“东城”的所在节点(City) 2.得到“东城”的Name属性值和Code属性值 3.得到“延庆”
public static void test2(Document doc) {
//找“东城”的所在节点(City)
Element sELem = (Element)doc.getElementsByTagName("State").item(0);
//只找当前State下的City
Element cElem = (Element)sELem.getElementsByTagName("City").item(0);
//得到“东城”的Name属性值和Code属性值
System.out.println(cElem.getNodeName());
System.out.println(cElem.getAttribute("Name"));
System.out.println(cElem.getAttribute("Code"));
//得到“延庆”
NodeList nl = sELem.getElementsByTagName("City");
int len = nl.getLength();
Element elem = (Element)sELem.getElementsByTagName("City").item(len - 1);
System.out.println(elem.getTextContent());
}
//修改节点 1.添加一个新的“State” 2.在新的“State”增加Name属性,“广东”,Code为“13” 3.在新的“State”添加一个新的“City” 4.新的“City”文本设置为广州
public static void test3(Document doc) throws Exception {
//添加一个新的“State”
Element newElem = doc.createElement("State");
//在新的“State”增加Name属性,“广东”,Code为“13”
newElem.setAttribute("Name", "广东");
newElem.setAttribute("Code", "13");
//在新的“State”添加一个新的“City”
Element cityElem = doc.createElement("City");
//新的“City”文本设置为广州
cityElem.setTextContent("广州");
newElem.appendChild(cityElem);
Node root = doc.getElementsByTagName("Location").item(0);
root.appendChild(newElem);
//1.创建TransformerFactory实例。
TransformerFactory factory = TransformerFactory.newInstance();
//2.通过TransformerFactory实例创建Transformer。
Transformer ts = factory.newTransformer();
//3.通过Transformer的transfer方法把Document写出xml文件。
ts.transform(new DOMSource(doc), new StreamResult("src/Locale.xml"));
}
//删除节点 1.删除“Name="滨海新区"” 2.删除“<City Name="津南" Code="12"/>”
public static void test4(Document doc) throws Exception {
//删除“Name="滨海新区"”
//得到所在元素
Element sElem = (Element)doc.getElementsByTagName("State").item(1);
Element cElem = (Element)sElem.getElementsByTagName("City").item(6);
//删除Name属性
cElem.removeAttribute("Name");
//删除“<City Name="津南" Code="12"/>”
Element cElem2 = (Element)sElem.getElementsByTagName("City").item(9);
sElem.removeChild(cElem2);
//1.创建TransformerFactory实例。
TransformerFactory factory = TransformerFactory.newInstance();
//2.通过TransformerFactory实例创建Transformer。
Transformer ts = factory.newTransformer();
//3.通过Transformer的transfer方法把Document写出xml文件。
ts.transform(new DOMSource(doc), new StreamResult("src/Locale.xml"));
}
}
Locale.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Location>
<State Code="11" Name="北京">
<City Code="1" Name="东城"/>
<City Code="2" Name="西城"/>
<City Code="5" Name="朝阳"/>
<City Code="6" Name="丰台"/>
<City Code="7" Name="石景山"/>
<City Code="8" Name="海淀"/>
<City Code="9" Name="门头沟"/>
<City Code="11" Name="房山"/>
<City Code="12" Name="通州"/>
<City Code="13" Name="顺义"/>
<City Code="21" Name="昌平"/>
<City Code="24" Name="大兴"/>
<City Code="26" Name="平谷"/>
<City Code="27" Name="怀柔"/>
<City Code="28" Name="密云"/>
<City>延庆</City>
</State>
<State Code="12" Name="天津">
<City Code="1" Name="和平"/>
<City Code="2" Name="河东"/>
<City Code="3" Name="河西"/>
<City Code="4" Name="南开"/>
<City Code="5" Name="河北"/>
<City Code="6" Name="红桥"/>
<City Code="26" Nmae="滨海新区"/>
<City Code="10" Name="东丽"/>
<City Code="11" Name="西青"/>
<City Code="12" Name="津南"/>
<City Code="13" Name="北辰"/>
<City Code="21" Name="宁河"/>
<City Code="22" Name="武清"/>
<City Code="23" Name="静海"/>
<City Code="24" Name="宝坻"/>
<City Code="25" Name="蓟县"/>
</State>
</Location>
修改后的文件:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><Location>
<State Code="11" Name="北京">
<City Code="1" Name="东城"/>
<City Code="2" Name="西城"/>
<City Code="5" Name="朝阳"/>
<City Code="6" Name="丰台"/>
<City Code="7" Name="石景山"/>
<City Code="8" Name="海淀"/>
<City Code="9" Name="门头沟"/>
<City Code="11" Name="房山"/>
<City Code="12" Name="通州"/>
<City Code="13" Name="顺义"/>
<City Code="21" Name="昌平"/>
<City Code="24" Name="大兴"/>
<City Code="26" Name="平谷"/>
<City Code="27" Name="怀柔"/>
<City Code="28" Name="密云"/>
<City>延庆</City>
</State>
<State Code="12" Name="天津">
<City Code="1" Name="和平"/>
<City Code="2" Name="河东"/>
<City Code="3" Name="河西"/>
<City Code="4" Name="南开"/>
<City Code="5" Name="河北"/>
<City Code="6" Name="红桥"/>
<City Code="26"/>
<City Code="10" Name="东丽"/>
<City Code="11" Name="西青"/>
<City Code="13" Name="北辰"/>
<City Code="21" Name="宁河"/>
<City Code="22" Name="武清"/>
<City Code="23" Name="静海"/>
<City Code="24" Name="宝坻"/>
<City Code="25" Name="蓟县"/>
</State>
<State Code="13" Name="广东"><City>广州</City></State></Location>
jaxp核心dom解析的api:
读取xml文件:
1)DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
2)DocumentBuilder builder = factory.newDocumentBuilder();
3) Document doc = builder.parse(“xml路径”);
写出xml文件:
1) TransformerFactory factory = TransformerFactory.newInstance();
2) Transformer ts = factory.newTransformer();
3) ts.transform(new DOMSource(document), new StreamResult(“xml路径”));
把哪个对象放到哪里去
查询:
document.getElementsByTagName(“name”) 读当前文档下的子元素
document.getElementById(“id”)
element.getElementsByTagName(“name”) 读当前元素下的子元素
element.getAttribute(“name”); 读取属性
element.getTextContent() 读取文本
创建或修改:
document.createElement(“name”); 创建元素
element.setAttribute(“name”,“value”) 创建或修改属性
element.setTextContent(“value”) 修改元素的文本内容
插入和删除:
element.appendChild(element) 把元素放入指定元素的子元素下
element.removeChild(element) 把元素从指定元素的子元素下删除
element.removeAttribute(“name”) 删除某个元素内的属性
-
jaxp的小练习(必须练习)