我为什么要学习XML?
在编程开发中我们使用XML作为程序之间数据传输的载体,无论这些程序用任何语言编写,运行在任何和平台上,XML都能很好的做到信息的传输。各种框架也使用XML作为配置文件(如spring、mybatis、maven),对XML有个基本的了解和感性的认识是很有必要的。
什么是XML?
XML和HTML的不同之处?
通过下边的事例来直观的认识XML
<note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>
上边的XML具有自我描述性,Tove发给了Jani一条信息,标题是 “Reminder”,内容是 “Dont‘t forget me this weekend!”。但是这个XML没有做任何事情,仅仅是将纯粹的信息包装在了XML中。我们需要编写程序才能解析和传递XML。总之一句话 XML是独立于平台和软件的信息传输工具,XML简化了数据的共享和存储。
XML语法
如果元素的文字内容包括“<”,会发生错误,因为解析器会将"<"作为新元素的开始来识别。“&”会被解析成实体引用的开始。这样的XML会产生错误:
<message>if salary < 1000 then</messag>
为了避免这个错误,请使用实体字符来代替“<”字符:
注释:在 XML 中,只有字符 "<" 和 "&" 确实是非法的。大于号是合法的,但是用实体引用来代替它是一个好习惯。
<message>if salary < 1000 then</message>在XML中有5个预定义的实体引用:
< | < | less than |
> | > | greater than |
& | & | ampersand |
' | ' | apostrophe |
" | " | quotation mark |
注释:在 XML 中,只有字符 "<" 和 "&" 确实是非法的。大于号是合法的,但是用实体引用来代替它是一个好习惯。
什么是XML元素?
XML元素是指从开始标签直到结束标签的部分。XML元素可以包含属性、文本内容和其它元素,或者以上混合。在给出的XML事例中<note>和</note>被称为开始和结束标签,<note></note>和之间的内容被成为元素。
XML的命名规则
- 可以包含字母、数字和其它字符。
- 不能已符号和数组开头。
- 名称不能包含空格。
- 不能已XML或xml开头。
因为xml用于声明xml文档,“
<?xml version="1.0" encoding="ISO-8859-1"?>”表示xml文档的版本是1.0,字符编码是ISO-8859-1。
验证XML的两种方式
有些时候我们需要验证XML是否符合一定的结构规则,这个时候我们可以使用XML DTD和XML Schema来验证。比如我们想验证上面的XML中note只能包含to、form、heading、body元素,不能包含其它元素。
DTD验证XML
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE note SYSTEM "Note.dtd"> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>Note.dtd文件内容:
<!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)><!DOCTYPE root-element SYSTEM "filename">代表引入note.dtd文件来校验note.xml。如果我们在note添加一个元素或删除其中一起元素都会提示错误。注意:在IDE中中才能看见这种错误。
XMLSchema校验XML
note.xml
<?xml version="1.0" encoding="UTF-8"?> <note xmlns="note_ns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="note_ns note.xsd"> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>note.xsd
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="note_ns" xmlns="note_ns" elementFormDefault="qualified"> <xs:element name="note"> <xs:complexType> <xs:sequence> <xs:element name="to" type="xs:string"/> <xs:element name="from" type="xs:string"/> <xs:element name="heading" type="xs:string"/> <xs:element name="body" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>像spring、mybatis的配置文件都是使用这种方式校验XML。
XML命名空间
有时候我们需要在一个XML文档中定义相同名称的元素,例如table.xml文件:
table.xml
spring-context.xml
<root> <table> <tr> <td>Apples</td> <td>Bananas</td> </tr> </table> <table> <name>African Coffee Table</name> <width>80</width> <length>120</length> </table> </root>第一个table代表HTML表格数据,第二个table代表桌子信息,两个table元素完全是两种类型。可以通过XML的命名空间来区分这两种类型。如下:
table.xml
<root xmlns="http://ttt.com" xmlns:h="http://www.table1.com" xmlns:f="http://www.table2.com"> <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> <a></a> </root>xmlns是XML 命名空间属性,语法:
xmlns:namespace-prefix="namespaceURI"命名空间属性被定义在根开始标签或应用这一命名空间的开始标签(也可将xmlns属性定义在table开始标签上),所有带有前缀的子元素都属于这一命名空间。上段的第一个table元素属于h命名空间,第二个table属于f命名空间,xmlns定义了默认的命名空间,就是没有前缀。namespaceURI用于标示命名空间的地址不会被解析器用于查找信息。其惟一的作用是赋予命名空间一个惟一的名称。不过,很多公司常常会作为指针来使用命名空间指向实际存在的网页,这个网页包含关于命名空间的信息。在看一个我们比较熟悉的XML片段。
spring-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:websocket="http://www.springframework.org/schema/websocket" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">spring-context.xml文件的beans元素声明了xsi、task、mvc等命名空间。
XML的CDATA区段(CDATA section)
CDATA是指不应该被XML解析器进行解析的文本数据(
Unparsed Character Data)。CDATA的作用是不让解析器去解析区段内的文本数据。XML解析器会默认解析XML文档中的所有文本(PCDATA 指的是被解析的字符数据(Parsed Character Data)),假如我们元素的文本内容是一断 HTML、JavaScript、java、代码,这些代码中通常带有“<”、“&”等XML非法字符,“<”会被解析成开始标签,“&”会被解析成实体引用的开始,用实体引用替换这些字符又非常繁琐。这种情况我们可以把我们的代码放在CDATA区段中,让解析器不去解析段中的文本数据。例如:
<script_tag> <![CDATA[function add(){docuemnt.wirit("<div></div>");}]]> </script_tag>CDATA区段以"<![CDATA["开始,以"]]>"结束。下段XML片段是CDATA区段在mybatis mapping xml文件的应用。
<select id="getWz_Ldzlbhqs" resultType="map" > select date_format(bug_find_time,'%Y-%m-%d')sj,count(*) count from base_bugs where 1=1 <if test="st != null and st != ''"> <![CDATA[ and bug_find_time >= #{st}]]> </if> <if test="et != null and et != ''"> <![CDATA[ and bug_find_time <= #{et} ]]> </if> GROUP BY sj order by sj asc </select>关于CDATA注意两点: