XML的全称是eXtensible Markup Language,即“可扩展标记语言”。XML文件的作用主要是数据存储,文件配置,数据传输。
html与xml的区别是:①html语法松散,xml语法严格;②html做页面展示,xml做数据存储;③html的所有标签都是预定义的,xml所有标签都是自定义的。xml文档中必须有且只能有一个根元素;元素需要正确闭合;元素需要正确嵌套;元素名称要遵守两点,一是元素名称区分大小写,二是数字不能开头;属性值必须用引号引起来,单双引号都行;xml文档中的注释符为<!-- -->;xml文档中对于可能引起歧义的文本要使用转义字符,或者用<![CDATA[数据内容]],这样的话,数据内容可以原样显示。
<?xml version="1.0" encoding="UTF-8" ?> <自定义标签> ... </自定义标签>
xml的书写规则,有DTD和schema。
文档类型定义(DTD)可以定义合法的XML文档构建模块,约束自定义的语法规则。它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
内部的 DOCTYPE 声明:
<!DOCTYPE 根元素 [元素声明]>
带有 DTD 的 XML 文档实例:
<?xml version="1.0"?> <!DOCTYPE note [ <!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)> ]> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note>
以上 DTD 解释如下:
!DOCTYPE note (第二行)定义此文档是 note 类型的文档。
!ELEMENT note (第三行)定义 note 元素有四个元素:"to、from、heading,、body"
!ELEMENT to (第四行)定义 to 元素为 "#PCDATA" 类型
!ELEMENT from (第五行)定义 from 元素为 "#PCDATA" 类型
!ELEMENT heading (第六行)定义 heading 元素为 "#PCDATA" 类型
!ELEMENT body (第七行)定义 body 元素为 "#PCDATA" 类型
假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:
<!DOCTYPE 根元素 SYSTEM "文件名">
这个 XML 文档和上面的 XML 文档相同,但是拥有一个外部的 DTD:
<?xml version="1.0"?> <!DOCTYPE note SYSTEM "note.dtd"> <note> <to>George</to> <from>John</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note>
这是包含 DTD 的 "note.dtd" 文件:
<!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)>
通过 DTD,我们的每一个 XML 文件均可携带一个有关其自身格式的描述。通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。我们的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。我们还可以使用 DTD 来验证自身的数据。
XML Schema 的作用是定义 XML 文档的合法构建模块,类似 DTD。它是基于 XML 的 DTD 替代者。XML Schema 描述 XML 文档的结构。XML Schema 语言也称作 XML Schema 定义(XML Schema Definition,XSD)。
XML Schema 最重要的能力之一就是对数据类型的支持。例:
user.xsd <?xml version="1.0"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.itszt2.com" xmlns="http://www.itszt2.com"> <xs:element name="用户" type="type_user"></xs:element> <!-- 复合类型;元素嵌套;自定义数据类型 --> <xs:complexType name="type_user"> <!-- 规定显示的先后顺序 --> <xs:sequence> <xs:element name="姓名" type="type_xm"></xs:element> <xs:element name="年龄" type="type_nl"></xs:element> <xs:element name="性别" type="type_xb" minOccurs="1" maxOccurs="999999999"></xs:element> <xs:element name="工资" type="type_gz"> </xs:element> <xs:element name="出生日期" type="xs:date"></xs:element> </xs:sequence> </xs:complexType> <!-- 定义姓名的类型 --> <xs:simpleType name="type_xm"> <xs:restriction base="xs:string"> <xs:pattern value="w{6,10}" /> </xs:restriction> </xs:simpleType> <!-- 定义年龄的类型 --> <xs:simpleType name="type_nl"> <xs:restriction base="xs:integer"> <xs:minInclusive value="0"></xs:minInclusive> <xs:maxInclusive value="100"></xs:maxInclusive> </xs:restriction> </xs:simpleType> <!-- 定义性别类型 --> <xs:simpleType name="type_xb"> <xs:restriction base="xs:string"> <xs:enumeration value="男" /> </xs:restriction> </xs:simpleType> <!-- 定义属性 --> <xs:complexType name="type_gz"> <xs:attribute name="单位" type="xs:string" use="required" /> <xs:attribute name="num" type="xs:decimal" /> </xs:complexType> </xs:schema> ------------------------------------------------------------- test.xml <?xml version="1.0"?> <用户 xmlns="http://www.itszt2.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.itszt2.com user.xsd"> <姓名>hehe123</姓名> <年龄>20</年龄> <性别>男</性别> <工资 单位="元" num="123.45" ></工资> <出生日期>1999-10-10</出生日期> </用户>
上述演示中,xmlns="http://www.w3school.com.cn" 规定了默认命名空间的声明。此声明会告知 schema 验证器,在此 XML 文档中使用的所有元素都被声明于 "http://www.w3school.com.cn" 这个命名空间。
定义简易元素的语法:
<xs:element name="xxx" type="yyy"/>
上面的 xxx 指元素的名称,yyy 指元素的数据类型。XML Schema 拥有很多内建的数据类型。
最常用的类型是: xs:string xs:decimal xs:integer xs:boolean xs:date xs:time
简易元素可拥有指定的默认值或固定值。当没有其他的值被规定时,默认值就会自动分配给元素。在下面的例子中,缺省值是 "red":
<xs:element name="color" type="xs:string" default="red"/>
固定值同样会自动分配给元素,并且我们无法规定另外一个值。在下面的例子中,固定值是 "red":
<xs:element name="color" type="xs:string" fixed="red"/>
简易元素无法拥有属性。假如某个元素拥有属性,它就会被当作某种复合类型。但是属性本身总是作为简易类型被声明的。
定义属性的语法是:
<xs:attribute name="xxx" type="yyy"/>
在此处,xxx 指属性名称,yyy 则规定属性的数据类型。XML Schema 拥有很多内建的数据类型,与上面定义元素的类型相同。
限定(restriction)用于为 XML 元素或者属性定义可接受的值。对 XML 元素的限定被称为 facet。
复合元素指包含其他元素及/或属性的 XML 元素。
有四种类型的复合元素: 空元素 包含其他元素的元素 仅包含文本的元素 包含元素和文本的元素 注释:上述元素均可包含属性!
比如,导入xsd约束文档:
(1)编写根标签 (2)引入实例名称空间 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" (3)引入名称空间 xsi:schemaLocation="http://www.itcast.cn/xml student.xsd" (4)引入默认的名称空间
在Java技术中,对xml文件的操作也是一个重要的部分。一般来说,xml的格式比较标准,在存储数据方面有着广泛的运用,例如,很多软件(如tomcat,nginx,redis等),包括框架(如Spring,mybatis等)中的一系列配置文件,就广泛地采用了xml来储存配置信息。接下来,我们看如何使用dom4j来对xml文件中的元素进行增删改查。
在使用dom4j技术时,我们需要在项目中引入dom4j-1.6.1.jar和jaxen-1.1-beta-6.jar两个jar包,并设置为依赖,这样的话,我们就可以使用这两个jar包中的API了。当然,也可以导入dom4j的其他版本,请根据需要而定。
我们先来看读取一个xml文件,并打印到控制台上:
1 import org.dom4j.Document; 2 import org.dom4j.DocumentException; 3 import org.dom4j.io.SAXReader; 4 import org.dom4j.io.XMLWriter; 5 import java.io.File; 6 import java.io.IOException; 7 /** 8 * 读取一个xml文件,并将其内容打印到控制台上 9 */ 10 public class Test1 { 11 public static void main(String[] args) { 12 String filePath = "book.xml"; 13 Document document = readXMLFile(filePath); 14 printToControl(document); 15 } 16 private static void printToControl(Document document) {//打印到控制台 17 try { 18 XMLWriter writer = new XMLWriter(); 19 writer.write(document); 20 writer.flush(); 21 writer.close(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } 25 } 26 private static Document readXMLFile(String filePath) {//读取一个xml文件 27 SAXReader saxReader = new SAXReader(); 28 File file = new File(filePath); 29 try { 30 return saxReader.read(file); 31 } catch (DocumentException e) { 32 e.printStackTrace(); 33 } 34 return null; 35 } 36 }
执行上述代码,读取到名称为book.xml的文件内容如下:
<?xml version="1.0" encoding="UTF-8"?> <图书信息 desc="书籍信息"> <图书> <书名>《战争与和平》</书名> <作者>列夫·托尔斯泰</作者> <内容>描述了拿破仑争霸时期,以俄国为社会背景的爱恨情仇</内容> </图书> <图书> <书名>《红楼梦》</书名> <作者>曹雪芹</作者> <内容>以贾王史薛四大家族为背景,描述了贾宝玉与林黛玉的感人爱情故事</内容> </图书> </图书信息>
我们还可以把读取到的xml文件储存到一个文件里,在此,我们在上述的Test1类里增加一个储存xml文件的方法,代码如下:
//保存xml文件到指定路径 static boolean saveDocument(Document document,String filePath){ OutputFormat outputFormat = OutputFormat.createPrettyPrint(); outputFormat.setEncoding("UTF-8"); XMLWriter writer = null; try { writer = new XMLWriter(new FileWriter(filePath), outputFormat); writer.write(document); writer.flush(); writer.close(); return true; } catch (IOException e) { e.printStackTrace(); } return false; }
上述代码执行成功后,会在项目下创建一个名称为book2.xml的文件,并返回为true。
另外,我们还可以创建一个xml文件,这个方法返回一个Document对象,代码如下:
//创建一个xml文件 public static Document createXMLDoc() { Document document = DocumentHelper.createDocument(); Element root = DocumentHelper.createElement("图书信息"); document.setRootElement(root); root.addAttribute("desc","书籍信息"); Element book1 = root.addElement("图书"); Element book1_name = book1.addElement("书名"); book1_name.addText("《战争与和平》"); Element book1_author = book1.addElement("作者"); book1_author.addText("列夫·托尔斯泰"); Element book1_content = book1.addElement("内容"); book1_content.addText("描述了拿破仑争霸时期,以俄国为社会背景的爱恨情仇"); Element book2 = root.addElement("图书"); Element book2_name = book2.addElement("书名"); book2_name.addText("《红楼梦》"); Element book2_author = book2.addElement("作者"); book2_author.addText("曹雪芹"); Element book2_content = book2.addElement("内容"); book2_content.addText("以贾王史薛四大家族为背景,描述了贾宝玉与林黛玉的感人爱情故事"); return document; }
我们还可以获取父元素下指定名称的第一个节点,代码如下:
//获取父元素下的指定名称第一个节点 static Element getFirstChildNodeByName(Element root,String nodeName){ return (Element)root.selectSingleNode(nodeName); }
我们还可以父元素下指定名称的所有节点信息,代码如下:
//获取父元素下的指定名称的所有节点 static List<Element> getAllChildNodeByName(Element root, String nodeName){ return root.selectNodes(nodeName); }
我们再来看删除指定节点的属性,代码如下:
//删除指定节点的属性 static void removeAttr(Element root,String nodeName,String attrName){ Element node = root.element(nodeName); Attribute attr = node.attribute(attrName); node.remove(attr); }
更改指定节点的属性值,代码如下:
//更改指定节点的属性值 static void updateAttrVal(Element root,String nodeName,String attrName,String newValue){ Element node = root.element(nodeName); Attribute attr = node.attribute(attrName); attr.setValue(newValue); }
为指定节点添加属性值,代码如下:
//为指定节点添加属性 static void addAttr(Element node, String attrKey, String attrValue) { node.addAttribute(attrKey, attrValue); }
对指定节点添加子节点及其文本内容,代码如下:
//对指定节点添加子节点及其文本内容 static Element addNode(Element parentNode,String childNode){ Element element = parentNode.addElement(childNode); element.setText("haha"); return element; }