XML笔记
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
XML笔记
第一天:
1、XML是什么?
(1)XML是一种元标记语言
标记语言:
由标记和代码组成,告诉应用程序如何处理。
特殊用途标记语言:
HTML(Hyper Text Markup Language)
例子:
<?xml version="1.0"?>
<!-- sample-->
<bookstore>
<book>
<bookname>java</bookname>
<author>mli</author>
</book>
<book>
<bookname>c++</bookname>
<author>sherry</author>
</book>
</bookstore>
一般用途标记语言:
SGML(Standard Generalized Markup language)
(2)XML的核心是数据
文档的三个组成部分:
数据、结构、样式(示例:书信)
XML将文档数据与文档样式(XSL,CSS)、结构分离(DTD,SCHEMA)。
(3)XML文档的树型结构
示例:
first.xml
(4)XML的优点
自我描述性
内容与样式分离
支持Unicode字符集
(5)XML的使用场合
1、数据交换
2、Web服务
3、内容管理
4、Web集成
5、配制
2、XML文档的框架结构
XML文档=序言+元素+杂项(可选)
1)序言
序言=(XML声明)+(杂项)+(文档类型声明)
XML声明
<?xml版本信息(编码信息) (文档独立性信息) ?>
如:<?xml version="1.0" encoding="gb2312" standalone="yes"?>
文档类型声明
规定元素的结构和属性列表的取值
如:<!DOCTYPE studinfo SYSTEM "studinfo.dtd">
2)元素
空元素
<空元素标签名属性="属性值"/>
非空元素
<起始标签>内容<结束标签>
内容=(子元素|字符数据|字符数据段|引用|处理指令|注释)*
子元素
字符数据
字符数据中,不能含有&,<,>,',",需要采用实体引用的方式
字符数据段
<![CDATA[字符数据]]>
引用
实体引用
例子:
<?xml version="1.0" encoding="gb2312"?>
<!--this is a comment
hehe
-->
<student>
<script>
<!-- 字31526 数25454 -->
<hello>
"zhangshan"&
'lishi'
<!-- 字31526 数25454 段-->
<![CDATA[
function compare(a,b){
if(a>b)
then {return 1}
else{return 0}
}]]>
</script>
<name country="china">张19977 </name>
</student>
--------------------------------------------------------------------------------
3)杂项
处理指令
XML为其它应用程序准备的接口。
<?处理指令?>
注释
<!-- 注释内容-->
空白符
指空格、回车等
3、格式良好的XML文档
(1)文档声明位于文件的开头,“xml"与“<?"之间无空格!
(2)唯一根元素
(3)标记必须闭合
(4)层层嵌套
(5)大小写敏感
(6)属性必须使用引号
(7)注意特殊字符
DTD笔记
1.DTD是什么?
文档类型定义
2.DTD的调用
方式一:调用内部文档类型定义。
注意点:
(1)studinfo与(#PCDATA)有空格
如:限定在这段代码中使用字符串:
<!ELEMENT studinfo (#PCDATA)>
(2)文档类型名与根元素名必须一致
方式二:
调用外部文档类型定义,
注意点:
(1)standalone="no"
(2)注意dtd文件的路径
例子:
<?xml version=”1.0”standalone=”no”?>
<!DOCTYPE studinfo [<!ELEMENT studinfo (#PCDATA)>]>
<studinfo></studinfo> //定义之后不能在到他们之间加入字符串引入了DOCTYPE:引入一个文档类型的申明
studinfo:文档类型名,
SYSTEM:关键字
3.DTD的结构
元素类型声明
指明元素的名称和元素含有的内容。
元素类型声明=<!ELEMENT 元素名(元素内容说明)
元素内容说明='EMPTY'|'ANY'|混合内容|元素内容|'#PCDATA'
#PCDATA:
只有可析的字符数据才能作为元素的内容
元素内容:
元素内部只能出现指定的子元素
示例dtd3.xml,studinfo3.dtd
EMPTY内容:
示例dtd4.xml,studinfo4.dtd
ANY:
混合内容:
标记文本和可析字符串
属性表声明
属性:由“=”分隔的成对的属性名和属性值构成,只能出现在元素标记的内部。
结束标记不能带属性,一个元素可以具有多个属性
语法:
<!ATTLIST 对应的元素名属性名属性取值类型属性默认值>
属性取值类型
1、CDATA:可析字符
2、Enumerated:枚举类型,由“|”分隔的可能的属性值列表
属性默认值:
注意
1、#REQUIRED:必须提供属性值
2、IMPLIED:可提供也可不提供
3、FIXED:不能修改
实体声明
实体:存储了任意符合规则的xml文档单元片断。
1、内部通用实体
定义格式
<!ENTITY 实体名“实体内容”>
引用格式
&实体名;
2、外部通用实体
<!ENTITY 实体名SYSTEM “外部实体的URI”>
引用格式
&实体名;
例子:
声明为是一个xml,支持版本为1.0 的文件,并需要DTD的验证.
<?xml version="1.0" standalone="no"?>
定义注释语句.
可以用两种方式来调用DTD文件:
1,内部引用:可以把注释语句中的代码作为正常运行语句,用<!DOCTYPE teacher[]> ,来包含在中括号里面.而不需要注释下面那一语句.其它语句不变.
2,外部引用:将注释中的代码另外生成一个名为:teacher.dtd文件,然后在teacher.xml文件中就使用以下语句进行调用即可.
<!--
定义一个元素teacher,并包含三个子元素,而且student+为在调用时可支持多个student子元素.
<!ELEMENT teacher (name,age,student+)>
定义子元素,并定义为只可析的字符数据才能作为元素的内容
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
定义子元素,并把这个子元素作为继续包含孙子元素的父元素,因为上面定义过了这两个孙子元素同名的子元素.所以以下可以不在定义这两个孙子元素.
<!ELEMENT student (name,age)>
定义teacher元素的熟悉course,CDATA:可析字符,#REQUIRED:调用语句中必须提供属性值
<!ATTLIST teacher course CDATA #REQUIRED>
定义一个枚举类型,并设置默认值为fish.
<!ATTLIST teacher course (fish|play|read) "fish" >
-->
用于外部调用语句,在没有上面语句时,可以调用teacher.dtd来验证dtd文件.
<!DOCTYPE teacher SYSTEM "teacher.dtd">
xml标签语句主体开始,并因为上面声明的属性必需提供属性值.
<teacher course="math">
定义子元素的值
<name>chengzh</name>
<age>28</age>
<student>
定义孙子元素的值
<name>hegh</name>
<age>23</age>
</student>
可以支持多个student子元素,因为”+”声明了多个
<student>
<name>chenzy</name>
<age>24</age>
</student>
</teacher>
名域
1、作用:
解决XML文档中命名冲突的问题,即将
XML文档与引用URI标识的名域相结合,来
限定其中的元素和属性名。
2、名域的声明
(1)直接定义
xmlns:名域前缀="名域的URI"(唯一性)
类比:名字与身份证
(2)缺省定义
xmlns=名域的URI
3、名域的使用
(1)用名域限定元素
(2)用名域限定属性
4、名域的作用范围
名域能够把声明它的元素和该元素的所有子元素
关联起来,除非它们被其他的名域声明所覆盖。
例子:文件名为:namespace.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- namespace -->
下面的name可以为任意名字. Boy为第一域名空间.由关键字xmlns来指定第二域名空间.区别两个域名空间之间子元素.避免名字相同的子元素冲突.
<boy:name xmlns="hello!"
xmlns:girl="love!">
<name>chengzh</name>
<age>28</age>
<girl>
<girl:name>zhangbz</girl:name>
<girl:age>25</girl:age>
</girl>
</boy:name>
或:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- namespace -->
<boy xmlns:boy="hello!"
xmlns:girl="love!">
<name>chengzh</name>
<age>28</age>
<girl>
<girl:name>zhangbz</girl:name>
<girl:age>25</girl:age>
</girl>
</boy>
第二天:
一,xml文件(二与三都是针对一操作) <介绍schema功能>
<?xml version="1.0" encoding="UTF-8"?>
<!--定义xsd文件的位置,如果xsd没有定义目标名域,就必需用以下noN***来定义位置-->
<student xmlns:xsi="
/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="/home/soft01/heguanhua/workspace/corejava/XML/stu dent1.xsd"
id="1000">
<!-- xml来引用xsd
如果引用的xsd文件定义了目标名称空间的话,就要把noN***换成schemaLocation="xsd文件路径名",如:
xsi:schemaLocation="http://www.sd0606/student 这是目标名字空间
/home/soft01/heguanhua/workspace/corejava/XML/student3.xsd"这是原文件路径名
然后在把student换成tc:student xmlns:tc="http://www.sd0606/student" 来指定目标名称空间-->
<name>
<firstname>shang</firstname>
<lastname>zhang</lastname>
</name>
<age>
20
</age>
<mother>ll</mother>
<father>aa</father>
</student>
<!--
1,age的值必须是数字
2,name的值必须是字符串
3,name,age的顺序必须有先后顺序
4,student是根元素
5,name为复杂元素,包含两个子元素
6,在student3.xml里面来定义限制age在10-30之间和把name定义为枚举类型,为id 定义属性
定义两个子元素为可选项,至少选择一个.
-->
二,
<?xml version="1.0" encoding="UTF-8"?>
<!-- xsd与xsd之间引用:在下面语句中加入xmln:tc="http://www.sd0606/student"来指定地址空间
并加入:<xs:import namespace="http://www.sd0606/student"
schemaLocation="/home/soft01/heguanhua/workspace/corejava/XML/student3.xsd"></xs:i
mport>
来指定所要引用xsd文件的目标名字空间和文件路径名-->
<schema xmlns="/2001/XMLSchema">
<xs:element name="student">
<xs:complexType><!-- 元素有子元素或有属性,所以得定义成复杂类型-->
<xs:sequence><!-- 定义元素出现的顺序-->
<xs:element ref="name"><!-- 用
xs:element元素来引用name子元素-->
</xs:element>
<xs:element ref="age"><!-- 用xs:element 元素来引用age子元素-->
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- 定义name子元素为复杂类型,并定义其两个孙子元素-->
<xs:element name="name">
<xs:compleType>
<xs:sequence>
<!-- 利用ref来引用外部的两个已定义的孙子元素-->
<xs:element ref="firstname"></xs:element>
<xs:element ref="lastname"></xs:element>
</xs:sequence>
</xs:compleType>
</xs:element>
<!-- 定义两个孙子元素,并定义字符串类型由schema指定-->
<xs:element name="firstname"
type="xs:string"></xs:element>
<xs:element name="lastname"
type="xs:string"></xs:element>
<!-- age元素名称,并定义为整型-->
<xs:element name="age"
type="xs:int"></xs:element>
</schema>
三,
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="
/2001/XMLSchema"
xmlns:tc="http://www.sd0606/student"
targetNamespace="http://www.sd0606/student">
<!-- 由xmlns:tc来引入原名称空间-->
<!--当前xsd文件所定义的类型属于targetNamespace所指定的空间-->
<xs:element name="student">
<xs:complexType>
<xs:sequence>
<!--定义了一个names类型,在以下得到调用.可以用maxOccurs="unbounded"来声明可用多个name子元素-->
<xs:element name="name" type="names" maxOccurs="unbounded"></xs:element>
<!-- 把age元素定义为一个stuage类型,并通过下面的自定义简单类型实现-->
<xs:element name="age"
type="tc:stuage"></xs:element>
<xs:choice><!-- 用于可选项,但必须至少选一个元素-->
<xs:element
ref="father"></xs:element>
<xs:element
ref="mother"></xs:element>
</xs:choice>
</xs:sequence>
<!-- 定义student的属性-->
<xs:element name="id" type="xs:string"
use="required"></xs:element>
</xs:complexType>
</xs:element>
<!--自定义简单类型,一般用于扩展基本数据类型-->
<xs:simpleType name="stuage">
<!-- 用于限制数据类型扩展,base为基于什么类型-->
<xs:restriction base="xs:int">
<!-- minInclusive表示大于等于-->
<xs:minInclusive value="10"></xs:minInclusive>
<!-- minInclusive表示小于等于-->
<xs:maxInclusive value="30"></xs:maxInclusive>
</xs:restriction>
</xs:simpleType>
<!-- 自定义简单类型,实现name元素的枚举功能-->
<xs:simpleType name="names">
<!-- 用于限制数据类型扩展,base为基于字符串类型-->
<xs:restriction base="xs:string">
<!-- 枚举类型定义,值以value指定-->
<xs:enumeration value="zhang"></xs:enumeration>
<xs:enumeration value="san"></xs:enumeration>
</xs:restriction>
</xs:simpleType>
<!-- 自定义简单类型.实现对子元素的可选功能-->
<xs:simpleType>
<!-- 两个子元素至少选择一个,并限制为字符串类型-->
<xs:element name="father" type="xs:string"></xs:element>
<xs:element name="mother" type="xs:string"></xs:element>
</xs:simpleType>
</xs:schema>
解析器SAX与DOM
一,SAX解析器:
事件驱动。
当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。
优点:
不用事先调入整个文档,占用资源少;
SAX解析器代码比DOM解析器代码小,适于Applet,下载缺点:
不是持久的;事件过后,若没保存数据,那么数据就丢了;
无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;
使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少
SAX处理流程
<?xml version="1.0"?>
<samples>
<server>UNIX</server>
<monitor>color</monitor>
</samples>
分析这个代码片断的SAX 处理器一般情况下将产生以下事件:
Start document
Start element (samples)
Characters (white space)
Start element (server)
Characters (UNIX)
End element (server)
Characters (white space)
Start element (monitor)
Characters (color)
End element (monitor)
Characters (white space)
End element (samples)
SAX API 允许开发人员捕捉这些事件并对它们作出反应。
SAX 处理涉及以下步骤:
创建一个事件处理程序。
创建SAX 解析器。
向解析器分配事件处理程序。
解析文档,同时向事件处理程序发送每个事件。
选择DOM 还是选择SAX,这取决于下面几个因素:
应用程序的目的:
数据容量:
数据多少部分会被使用
对速度的需要:
对程序的实现:
1,XML文件(所要解析的文件)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dbconfig>
<username>t1</username>
<password>t2</password>
</dbconfig>
2,解析器程序:(一)
package sax.exec;
import java.util.Properties;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import .URL;
public class ParseXML {
// 定义一个Properties 用来存放dbhost dbuser dbpassword的值
private Properties props;
// 这里的props
public Properties getProps() {
return this.props;
}
public void parse(String filename) throws Exception {
// 将我们的解析器对象化
ConfigParser handler = new ConfigParser();
// 获取SAX工厂对象
SAXParserFactory factory = SAXParserFactory.newInstance(); // factory.setNamespaceAware(false);
// factory.setValidating(false);
// 获取SAX解析
SAXParser parser = factory.newSAXParser();
XMLReader xmlReader = parser.getXMLReader();
xmlReader.setContentHandler(handler);
InputSource source = new InputSource("dbconfig.xml");
xmlReader.parse(source);
props = handler.getProps();
}
public static void main(String[] args){
ParseXML test = new ParseXML();
try {
test.parse("");
Properties prop = test.getProps();
System.out.println(prop.getProperty("username"));
System.out.println(prop.getProperty("password"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
(二)
package sax.exec;
import java.util.Properties;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class ConfigParser extends DefaultHandler {
// //定义一个Properties 用来存放dbhost dbuser dbpassword的值
private Properties props;
private String currentName;
private StringBuffer currentValue = new StringBuffer();
// 构建器初始化props
public ConfigParser() {
this.props = new Properties();
}
public Properties getProps() {
return this.props;
}
// 定义开始解析元素的方法. 这里是将<xxx>中的名称xxx提取出来.
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
currentValue.delete(0, currentValue.length());
this.currentName = qName;
}
// 这里是将<xxx></xxx>之间的值加入到currentValue
public void characters(char[] ch, int start, int length)
throws SAXException {
currentValue.append(ch, start, length);
}
// 在遇到</xxx>结束后,将之前的名称和值一一对应保存在props中
public void endElement(String uri, String localName, String qName)
throws SAXException {
props.put(qName.toLowerCase(), currentValue.toString().trim());
}
}
DOM解析器
DOM (文档对象模型)
为XML 文档的已解析版本定义了一组接口。
解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用DOM 接口来操作这个树结构。
优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;
缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;
使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)
解析器程序:
package dom.sales.add;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Sales4 {
private static void visit (Node start)
{
System.out.println(start.getNodeName()+" = "+start.getNodeValue());
for (Node child = start.getFirstChild();
child != null;
child = child.getNextSibling())
{
visit(child);
}
}
/**
* @param args
*/
public static void main(String[] args) {
File docFile = new File("sales.xml");
Document doc = null;
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(docFile);
Element root = doc.getDocumentElement();
//第一步,找到所有order(订单)
NodeList orders =
root.getElementsByTagName("order");
//第二步,循环每个订单,进行处理
for (int orderNum = 0;
orderNum < orders.getLength();
orderNum++) {
Element thisOrder =
(Element) orders.item(orderNum);
//第三步,对每个订单,找到所有item
NodeList orderItems =
thisOrder.getElementsByTagName("item");
double total = 0;
//第四步,对每个item,循环汇总
for (int itemNum = 0;
itemNum < orderItems.getLength();
itemNum++) {
Element thisOrderItem =
(Element) orderItems.item(itemNum);
String thisPrice =
thisOrderItem.getElementsByTagName(
"price").
item(0).
getFirstChild().
getNodeValue();
double thisPriceDbl =
new
Double(thisPrice).doubleValue();
String thisQty =
thisOrderItem.getElementsByTagName("qty")
.item(0).getFirstChild().getNodeValue();
double thisQtyDbl = new Double(thisQty).doubleValue();
double thisItemTotal =
thisPriceDbl * thisQtyDbl;
total = total + thisItemTotal;
}
// 对当前order汇总
String totalString = new
Double(total).toString();
//第五步,利用Document的createTextNode方法创建文本节点
Node totalNode =
doc.createTextNode(totalString);
//第六步,利用Document的createElement
方法创建元素节点
Element totalElement =
doc.createElement("total");
//第七步,将刚刚创建的文本节点挂到刚刚创建的元素节点上
totalElement.appendChild(totalNode);
//第八步,将元素节点插入到order下
thisOrder.
insertBefore(totalElement,
thisOrder.getFirstChild());
}
visit(root);
} catch (Exception e) {
e.printStackTrace();
}
}
}
XML文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sales>
<order>
<custid limit="300">100</custid>
<status>true</status>
<item stock = "Y" itemid="1000">
<name>bmwcar</name>
<price>100.0</price>
<qty>2</qty>
</item>
<item stock="N" itemid="1001">
<name>qq</name>
<price>50.0</price>
<qty>1</qty>
</item>
</order>
<order>
<custid limit="300">200</custid>
<status>true</status>
<item stock = "Y" itemid="1001">
<name>benzcar</name>
<price>200.0</price>
<qty>2</qty>
</item>
</order>
</sales>。