一、什么是XML
- XML 指可扩展标记语言(EXtensible Markup Language)
- XML 是一种标记语言,很类似 HTML
- XML 的设计宗旨是传输数据,而非显示数据
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
- XML 是 W3C 的推荐标准
二、html与xml的区别
-
XML 不是 HTML 的替代。
-
XML 和 HTML 为不同的目的而设计:
-
XML 被设计为传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观 。
HTML 旨在显示信息,而 XML 旨在传输信息。
HTML语法比较松散,xml语法严格
HTML所有标签都是预先定义好的, 使用固定的标签,展示不同的内容 -
XML当中的标签都是自己定义的
-
XML用处,数据存储、配置文件、数据传输
三、XML的基本语法
1、文档声明
<?xml version="1.0">
可以添加以下属性
- version版本号,固定1.0
- encoding指定文档的码表 默认iso-8859-1
- standalone指定文档是否独立yes或no是否可以引用其它文件
注:文档声明必须放在第一行
2、规则
-
所有 XML 元素都须有关闭标签
-
XML 标签对大小写敏感
-
XML 必须正确地嵌套
-
XML 文档必须有根元素
-
XML 的属性值须加引号
-
实体引用
在 XML 中,一些字符拥有特殊的意义。如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。这样会产生 XML 错误:为了避免这个错误,请用实体引用来代替 "<" 字符:
以下是5 个预定义的实体引用
< < 小于 > > 大于 & & 和号 ' ' 单引号 " " 引号
-
元素命名规则
xml中的元素其实就是标签,名称可以含字母、数字以及其他的字符但是类似于其他语言一样,不能够以数字或标点符号开始,也不能够以字符“xml”、“XML”、“Xml”开始,并且名称中不能包含空格。
-
引用CDATA输出数据内容
<![CDATA[数据内容]]>
里面的数据会原样展示不会解析
-
xml元素中同样可以有属性
<?xml version="1.0" encording="utf-8"?> <team> <person id="1001"> <name>wen</name> <gender>男</gender> </person> <person id="1002"> <name>wenss</name> <gender>男</gender> </person> </team>
四、XML约束
xml约束规定了文档当中只能写写那些标签,并且会给出一些提示。主要分为DTD约束与schema两类约束
1、DTD
-
内部dtd
在xml当中定义的dtd,开发中不建议使用 -
外部dtd
在外部文件当中单独定义的dtd,扩展名为.dtd
本地:<!DOCTYPE 需要约束的名称 SYSTEM "需要约束的名.dtd">
网络:<!DOCTYPE students PUBLIC "命名空间" "student.dtd">
-
约束语法
例如:
web-app.dtd
<!ELEMENT web-app (servlet*,servlet-mapping*,wel-file-list?)>
<!ELEMENT servlet (servlet-name,description?,(servlet-class|jsp-file))>
<!ELEMENT servlet-name (#PCDATA)>
<!ELEMENT wel-file-list (welcome-file+)>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app SYSTEM "web-app.dtd">
<web-app>
<servlet>
<servlet-name></servlet-name>
<servlet-class>aaa</servlet-class>
</servlet>
<servlet>
<servlet-name>aaa</servlet-name>
<jsp-file>aaa</jsp-file>
</servlet>
<servlet-mapping></servlet-mapping>
<wel-file-list>
<welcome-file>aaa</welcome-file>
</wel-file-list>
</web-app>
student.dtd
<!ELEMENT students (student*) >
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student number ID #REQUIRED>
student.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
<student number="a001">
<name>张三</name>
<age>18</age>
<sex>男</sex>
</student>
<student number="a002">
<name>李四</name>
<age>20</age>
<sex>男</sex>
</student>
<student number="a0003">
<name>王五</name>
<age>30</age>
<sex>男</sex>
</student>
</students>
弊端:在标签当中存放的内容不知道是什么类型,写的都是汉字或英文数字等等,这种约束不严谨
2、schema
schema是一种既能够约束标签又能够约束标签中的类型的约束
-
使用过程
- 编写根标签
- 引用约束地址 xsi:schemaLocation="默认空间 约束地址.xsd"
- 引用实例名称空间 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- 默认名称空间 xmlns="http://www.it666.cn/xml"
-
语法
如上图一般schema分为复杂标签与简单标签
复杂标签标签(complexType)当中还有子标签
简单标签标签(simpleType)当中没有子标签
五、XML解析
1、XML文档结构
不难看出xml就是一种树形结构,我们可以对上述students例子画出一个示意图如下
- student.xml Document : 文档节点 xml文件
- students Element : 元素节点 使用<>的标签
- number Attr : 属性节点 元素上属性名=“属性值”
- zs Text : 文本节点 元素之间的内容
2、DOM
-
什么是DOM
DOM:Document Object Model:文档对象模型,把文档中的成员描述成一个个对象.
使用Java代码操作XML 或者 js代码操作HTML -
DOM解析的特点
在加载的时候,一次性的把整个XML文档加载进内存,在内存中形成一颗树(Document对象).以后使用代码操作Document,其实操作的是内存中的DOM树,和本地磁盘中的XML文件没有直接关系.由于操作的是内存当中的dom,磁盘中xml当中的内容并没有变,要进行同步,让两边保持一致。当然查询不需要同步,只有数据变化的时候,才需要同步
缺点:若XML文件过大,可能造成内存溢出. -
DOM解析步骤
- 创建解析器工厂
- 通过解析器工厂得到解析器
- 通过解析器得到document对象
- 获取具体的节点内容
// 1.创建解析器工厂 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 2.通过解析器工厂得到解析器 DocumentBuilder db = dbf.newDocumentBuilder(); // 3.通过解析器得到document对象 Document doc = db.parse("src/com/xml/parse/student.xml"); // 4.获取具体的节点内容 NodeList list = doc.getElementByTagName("name"); Node name = list.item(1); System.out.printlen(name.getTextContent());
上述代码为java获取student.xml中的name 输出结果为李四
-
DOM修改元素内容
- 获取所有指定节点
- 获取要修改的节点
- 修改元素内容
- 从内存写到文档做同步操作
// 修改元素的内容 static void updateElem(Document doc) throws TransformerFactoryConfigurationError, Exception { // 1.获取所有指定节点 NodeList ageList = doc.getElementsByTagName("age"); // 2.获取要修改的节点 Node ageNode = ageList.item(1); // 3.修改元素内容 ageNode.setTextContent("300"); // 4.从内存写到文档做同步操作 Transformer tf = TransformerFactory.newInstance().newTransformer(); tf.transform(new DOMSource(doc), new StreamResult("src/com/xml/parse/student.xml")); }
上述java代码先获取了节点名为age的节点并且取第1个值(0开始算),将第一个节点内容修改为300。如前文所说,我们现在所操纵的是内存中的xml树并不是真正的xml文件,所以我们还需要做第四步同步操作。同步操作与解析操作类似,我们首先需要创建一个传输工厂(TransformerFactory.newInstance()),然后创建一个传输器(tf),再通过传输器进行传输。tf.transform(xmlSource, outputTarget)传输器有两个参数,第一个为你要输出的new DOMSource(doc)源,第二个为new StreamResult(“src/com/xml/parse/student.xml”)流(从内存到文件一般使用流)。
-
DOM添加元素
- 创建一个节点
- 设置元素内容
- 获取要添加元素的父结点
- 在父节点中添加节点
- 从内存写到文档做同步操作
// 添加节点 static void addElem(Document doc) throws Exception, TransformerFactoryConfigurationError { // 1.创建一个节点 Element addressEle = doc.createElement("address"); // 2.设置元素内容 addressEle.setTextContent("地址1"); // 3.获取要添加元素的父结点 Node stuNode = doc.getElementsByTagName("student").item(0); // 4.添加节点 stuNode.appendChild(addressEle); // 5.从内存写到文档做同步操作 Transformer tf = TransformerFactory.newInstance().newTransformer(); tf.transform(new DOMSource(doc), new StreamResult("src/com/xml/parse/student.xml")); }
-
DOM删除元素
- 获取一个节点
- 获取该节点的父节点,从父节点当中移除
- 从内存写到文档做同步操作
// 删除节点 static void delElem(Document doc) throws Exception, TransformerFactoryConfigurationError { // 1.获取一个节点 Node addressNode = doc.getElementsByTagName("address").item(0); // 2.获取该节点的父节点,从父节点当中移除 addressNode.getParentNode().removeChild(addressNode); // 3.从内存写到文档做同步操作 Transformer tf = TransformerFactory.newInstance().newTransformer(); tf.transform(new DOMSource(doc), new StreamResult("src/com/xml/parse/student.xml")); }
-
DOM添加元素属性
- 获取要添加属性的节点
- 把获取的节点强制转换成element
- 设置属性
- 从内存写到文档做同步操作
static void addElemPro(Document doc) throws Exception, TransformerFactoryConfigurationError { //1.获取要添加属性的节点 Node stu = doc.getElementsByTagName("student").item(1); //2.把获取的节点强制转换成element Element ele = (Element)stu; //3.设置属性 ele.setAttribute("ID", "00001"); //4.从内存写到文档做同步操作 Transformer tf = TransformerFactory.newInstance().newTransformer(); tf.transform(new DOMSource(doc), new StreamResult("src/com/xml/parse/student.xml")); }
3.DOM4j
-
DOM4j简介
DOM4J是dom4j.org出品的一个开源XML解析包,dom4j是一个十分优秀的JavaXML API,具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom技术,同时它也是一个开放源代码的软件,越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这已经是必须使用的jar包, Hibernate也用它来读写配置文件。
-
DOM4j解析步骤
- 下载Dom4j的jar包
- 在工程根目录当中创建一个文件夹为lib
- 编译jar包
- 创建SAXReader
- 读取指定路径的xml
SAXReader reader = new SAXReader(); Document doc = reader.read("src\com\xml\dom4j\student.xml");
- 获取所有指定标签内容
- 创建SAXReader
- 获取根元素
- 获取根元素下所有的元素
- 遍历每一个子元素
- 获取指定名称的元素
- 获取标签当中的文本
static void test() throws Exception { //获取所有指定标签内容 //1.创建SAXReader SAXReader reader = new SAXReader(); Document doc = reader.read("src\com\xml\dom4j\student.xml"); //2.获取根元素 Element rootElement = doc.getRootElement(); //3.根据名称获取根元素下的所有标签 List<Element> stuList = rootElement.elements("student"); //4.遍历每一个子元素 for (Element stuEle : stuList) { //5.获取指定名称的元素 //Element nameEle = stuEle.element("name"); //System.out.println(nameEle.getText()); //6.获取标签当中的文本 //根据指定标签获取内容 String name = stuEle.elementText("name"); String age = stuEle.elementText("age"); String sex = stuEle.elementText("sex"); System.out.println(name); System.out.println(age); System.out.println(sex); String num = stuEle.attributeValue("number");//获取属性值 System.out.println(num); System.out.println("------"); } }
-
添加元素
1.创建SAXReader
2.获取根元素
3.给根元素添加元素和属性,并返回添加的元素
//1.创建SAXReader
SAXReader reader = new SAXReader();
Document doc = reader.read("src\com\xml\dom4j\student.xml");
//2.获取根元素
Element rootElement = doc.getRootElement();
//3.给根元素添加元素和属性,并返回添加的元素
Element stuEle = rootElement.addElement("student").addAttribute("number", "a0003");
stuEle.addElement("name").setText("王五");
stuEle.addElement("age").setText("30");
stuEle.addElement("sex").setText("男");
// Pretty print the document to System.out
OutputFormat format = OutputFormat.createPrettyPrint();
Writer wr = new OutputStreamWriter(new FileOutputStream("src/com/xml/dom4j/student.xml"),"UTF-8");
XMLWriter writer = new XMLWriter(wr, format);
writer.write( doc );
wr.close();