XML基础知识
1.定义:XML 指可扩展标记语言(eXtensible Markup Language)。
2.用途:XML 被设计用来传输和存储数据,在JAVA中的应用是用来定义各种各样的配置文件、储存对象数据等。
3.语法:
(1)文档声明:<?xml version="1.0" encoding="UTF-8"?>,注意,文档声明从文档的0行0列位置开始,encoding默认UTF-8,可选择,version版本号必须要定义,一般使用1.0版本。
(2)元素标签:元素标签必须被正确的关闭,例如<a></a>,如果是单标签也必须关闭,例如HTML中的<br>,在XML中要写作<br/>。
元素命名:不得含有空格,不能使用冒号,区分大小写,另外,不建议使用XML, xml, Xml,根元素只有一个。
<?xml version="1.0" encoding="UTF-8"?> <Person><!--根元素标签--> <Student></Student> <Worker></Worker> </Person>
(3)属性:
a.属性是元素的一部分,它必须出现在元素的开始标签中。
b.属性的定义格式:属性名=属性值,其中属性值必须使用单引或双引。
c.一个元素可以有O ~ N个属性,但一个元素中不能出现同名属性。
d.属性名不能使用空格、冒号等特殊字符,且必须以字母开头。
(4)注释标签:<!---->,和HTML语言相同
(5)转义字符:< > ' " &,这几个字符单独使用时必须使用转义字符
(6)CDATA区:在CDATA区中可以不使用转义字符
<?xml version="1.0" encoding="UTF-8"?> <![CDATA[ if(a<b&c<b){ } ]]>
4.DTD
DTD (Document Type Definition ),文档类型定义,用来约束XML文档。规定XML文档中元素的名称,子元素的名称及顺序,元素的属性等。
<?xml version="1.0" encoding="UTF-8"?> <!-- 模拟servlet2.3规范,如果开发人员需要在xml使用当前DTD约束,必须包括DOCTYPE。 格式如下: <!DOCTYPE web-app SYSTEM "web-app_2_3.dtd"> --> <!ELEMENT web-app (servlet*,servlet-mapping* , welcome-file-list?) > <!ELEMENT servlet (servlet-name,description?,(servlet-class|jsp-file))> <!ELEMENT servlet-mapping (servlet-name,url-pattern+) > <!ELEMENT servlet-name (#PCDATA)> <!ELEMENT servlet-class (#PCDATA)> <!ELEMENT url-pattern (#PCDATA)> <!ELEMENT description (#PCDATA)> <!ELEMENT jsp-file (#PCDATA)> <!ELEMENT welcome-file-list (welcome-file+)> <!ELEMENT welcome-file (#PCDATA)> <!ATTLIST web-app version CDATA #IMPLIED>
一个DTD文档可用在多个XML中,同时也可以引用网络资源,例
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app SYSTEM "web-app_2_3.dtd">//外部引用,两者在同一文件夹下 <web-app> <servlet> <servlet-name>TestMS</servlet-name> <servlet-class>edu.java.xml.TestMS</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestMS</servlet-name> <url-pattern>/ms</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>welcome</welcome-file> </welcome-file-list> </web-app>
元素声明:
PCDATA
PCDATA 的意思是被解析的字符数据(parsed character data)。
可把字符数据想象为 XML 元素的开始标签与结束标签之间的文本。
PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
文本中的标签会被当作标记来处理,而实体会被展开。
不过,被解析的字符数据不应当包含任何 &、< 或者 > 字符;需要使用 &、< 以及 > 实体来分别替换它们。
CDATA
CDATA 的意思是字符数据(character data)。
CDATA 是不会被解析器解析的文本。在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。
#REQUIRED:属性是必须的!
#IMPLIED:属性不是必须的
符号含义:
符号 |
符号类型
|
描述 |
? |
问号 |
表示该对象可以出现,但只能出现一次 |
* |
星号
|
表示该对象允许出现任意多次,也可以是零次 |
+ |
加号
|
表示该对象最少出现一次,可以出现多次 |
() |
括号
|
用来给元素分组 |
| |
竖条
|
表明在列出的对象中选择一个
|
, |
逗号 |
表示对象必须按指定的顺序出现 |
代码解析:
<?xml version="1.0" encoding="UTF-8"?> <!-- 模拟servlet2.3规范,如果开发人员需要在xml使用当前DTD约束,必须包括DOCTYPE。 格式如下: <!DOCTYPE web-app SYSTEM "web-app_2_3.dtd"> --> <!ELEMENT web-app (servlet*,servlet-mapping* , welcome-file-list?) >
//web-app标签下有3个子标签:servlet,可出现多次或0次,servlet-mapping,可出现一次或0次,welcome-file-list,最多出现一次 <!ELEMENT servlet (servlet-name,description?,(servlet-class|jsp-file))>
//servlet标签下有3个标签,servlet-name,必须且只能出现一次,description,最多出现一次,servlet-class/jsp-file二者任选其一,必须且只能出现一次 <!ELEMENT servlet-mapping (servlet-name,url-pattern+)>
//servlet-mapping标签下有2个子标签,servlet-name,必须且只能出现一次,url-pattern,至少出现一次 <!ELEMENT servlet-name (#PCDATA)>//文本 <!ELEMENT servlet-class (#PCDATA)>//文本 <!ELEMENT url-pattern (#PCDATA)>//文本 <!ELEMENT description (#PCDATA)>//文本 <!ELEMENT jsp-file (#PCDATA)>//文本 <!ELEMENT welcome-file-list (welcome-file+)>//welcome-file-list标签有1个子标签,welcome-file,至少出现一次 <!ELEMENT welcome-file (#PCDATA)>//文本 <!ATTLIST web-app version CDATA #IMPLIED>//字符数据 非必须
6.Schemas
XML Schema 是基于 XML 的 DTD 替代者。
XML Schema 语言也可作为 XSD(XML Schema Definition)来引用。
XML Schema 可描述 XML 文档的结构:
- 定义可出现在文档中的元素
- 定义可出现在文档中的属性
- 定义哪个元素是子元素
- 定义子元素的次序
- 定义子元素的数目
- 定义元素是否为空,或者是否可包含文本
- 定义元素和属性的数据类型
- 定义元素和属性的默认值以及固定值
优势:
- XML Schema 可针对未来的需求进行扩展
- XML Schema 更完善,功能更强大
- XML Schema 基于 XML 编写
- XML Schema 支持数据类型
- XML Schema 支持命名空间
<?xml version="1.0" encoding="UTF-8"?> <!-- 模拟servlet2.5规范,如果开发人员需要在xml使用当前Schema约束,必须包括指定命名空间。 格式如下: <web-app xmlns="http://www.example.org/web-app_2_5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd" version="2.5"> --> <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" //默认命名空间,无前缀 targetNamespace="http://www.example.org/web-app_2_5"//文件位置,显示被此 schema 定义的元素的命名空间。 xmlns:xsd="http://www.w3.org/2001/XMLSchema"//显示 schema 中用到的元素和数据类型来自命名空间 "http://www.w3.org/2001/XMLSchema"。
//同时它还规定了来自命名空间 "http://www.w3.org/2001/XMLSchema" 的元素和数据类型应该使用前缀 xsd: xmlns:tns="http://www.example.org/web-app_2_5" elementFormDefault="qualified">//指出任何 XML 实例文档所使用的且在此 schema 中声明过的元素必须被命名空间限定。 <xsd:element name="web-app"> <xsd:complexType> <xsd:choice minOccurs="0" maxOccurs="unbounded">//数量限制,最少0个,最大未规定 <xsd:element name="servlet"> <xsd:complexType> <xsd:sequence> <xsd:element name="servlet-name"></xsd:element> <xsd:element name="servlet-class"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="servlet-mapping"> <xsd:complexType> <xsd:sequence> <xsd:element name="servlet-name"></xsd:element> <xsd:element name="url-pattern" maxOccurs="unbounded"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="welcome-file-list"> <xsd:complexType> <xsd:sequence> <xsd:element name="welcome-file" maxOccurs="unbounded"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:choice> <xsd:attribute name="version" type="double" use="optional"></xsd:attribute>//属性,double类型,非必须使用 </xsd:complexType> </xsd:element> </xsd:schema>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://www.example.org/web-app_2_5" //规定了默认命名空间的声明。此声明会告知 schema 验证器,在此 XML 文档中使用的所有元素都被声明于该命名空间。
//一旦您拥有了可用的 XML Schema 实例命名空间: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
//您就可以使用 schemaLocation 属性了。此属性有两个值。第一个值是需要使用的命名空间。第二个值是供命名空间使用的 XML schema 的位置: xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name></servlet-name> <servlet-class></servlet-class> </servlet> <servlet-mapping> <servlet-name></servlet-name> <url-pattern></url-pattern> </servlet-mapping> </web-app>
7.命名空间:
在 XML 中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突,例:
<table> <tr> <td>Apples</td> <td>Bananas</td> </tr> </table> <table> <name>African Coffee Table</name> <width>80</width> <length>120</length> </table>
要解决这个问题,就要用到命名空间,简单来说就是给标签加前缀:
<h:table> <h:tr> <h:td>Apples</h:td> <h:td>Bananas</h:td> </h:tr> </h:table> <f:table> <f:name>African Coffee Table</f:name> <f:width>80</f:width> <f:length>120</f:length> </f:table>
进一步完善:为 <table> 标签添加一个 xmlns 属性,这样就为前缀赋予了一个与某个命名空间相关联的限定名称。
<h:table xmlns:h="http://www.w3.org/TR/html4/"> <h:tr> <h:td>Apples</h:td> <h:td>Bananas</h:td> </h:tr> </h:table> <f:table xmlns:f="http://www.w3school.com.cn/furniture"> <f:name>African Coffee Table</f:name> <f:width>80</f:width> <f:length>120</f:length> </f:table>
默认命名空间:为元素定义默认的命名空间可以让我们省去在所有的子元素中使用前缀的工作。
<table xmlns="http://www.w3.org/TR/html4/"> <tr> <td>Apples</td> <td>Bananas</td> </tr> </table> <table xmlns="http://www.w3school.com.cn/furniture"> <name>African Coffee Table</name> <width>80</width> <length>120</length> </table>
8.XML解析
要对XML文档中存储的数据进行读写,就要进行解析,开发中比较常见的解析方式有三种,如下:
1.DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象。
a) 优点:元素与元素之间保留结构关系,故可以进行增删改查操作。
b) 缺点:XML文档过大,可能出现内存溢出显现。
2.SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件 驱动的方式进行具体解析,每执行一行,都将触发对应的事件。
a) 优点:处理速度快,可以处理大文件
b) 缺点:只能读,逐行后将释放资源。
3. PULL: Android内置的XML解析方式,类似SAX。
注意,这里的DOM操作和JS中的DOM操作思想相同,简单来说就是根据一个个的节点来进行操作,同时也融合了JAVA中的反射思想。
开发中常用的是dom4j这个工具包:
import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class Test { public static void main(String[] args) { SAXReader sr = new SAXReader(); try { Document d = sr.read("src\\edu\\java\\xml\\Web.xml"); Element r = d.getRootElement();//获取根元素 System.out.println(r.getName()); List<Element> arr = r.elements();//获取所有子节点 for(Element e:arr) { //System.out.println(e.getName()); if("servlet".equals(e.getName())) { Element servletname = e.element("servlet-name");//获取子节点 String str = servletname.getText(); System.out.println(str); Element servletclass = e.element("servlet-class"); String c = servletclass.getText(); System.out.println(c); } } for(Element m:arr) { if("servlet-mapping".equals(m.getName())) { Element servletname = m.element("servlet-name"); String sn = servletname.getText(); Element urlpattern = m.element("url-pattern"); String url = urlpattern.getText(); System.out.println(sn); System.out.println(url); } } for(Element w:arr) { if("welcome-file-list".equals(w.getName())) { Element welcome = w.element("welcome-file"); String str = welcome.getText(); System.out.println(str); } } } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
利用反射的思维,我们可以在xml文件中填写一个包名,然后利用这个包名来进行一系列的操作:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app SYSTEM "web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>TestMS</servlet-name> <servlet-class>edu.java.xml.TestMS</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestMS</servlet-name> <url-pattern>/ms</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>welcome</welcome-file> </welcome-file-list> </web-app> public interface Myservlet { public void init(); public void service(); public void destroy(); } public class TestMS implements Myservlet{ public static void main(String[] args) { try { SAXReader sr = new SAXReader(); Document d = sr.read("src\\edu\\java\\xml\\Web.xml"); Element r = d.getRootElement();//获取根元素 Element servletname = r.element("servlet"); Element servletclass = servletname.element("servlet-class"); String name = servletclass.getText(); Class c = Class.forName(name); Object obj = c.newInstance(); Method init = c.getMethod("init"); Method service = c.getMethod("service"); Method destroy = c.getMethod("destroy"); init.invoke(obj); service.invoke(obj); destroy.invoke(obj); } catch (Exception e) { // TODO: handle exception } } @Override public void init() { System.out.println("初始化"); } @Override public void service() { System.out.println("服务"); } @Override public void destroy() { System.out.println("销毁"); } }