u 为什么需要xml
1. 提出问题?
两个程序间通信的时候,数据格式.
2. 用什么方式做配置文件
<serverinfo>
<ip></ip>
<port></port>
<user><user>
<passwd></passwd>
<driver></driver>
</serverinfo>
u 编码问题
默认iso-8859-1
ansi(美国国家标准协会) 编码 ,如果你是中文操作系统 ,则对应 gb2312 ,在日文操作系统上
utf-8编码 ,可以支持多种语言编码.
不同的国家和地区制定了不同的标准,由此产生了 GB2312, BIG5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。
XML声明由以下几个部分组成:
version- -文档符合XML1.0规范,我们学习1.0
encoding - -文档字符编码,比如”gb2312”
standalone- -文档定义是否独立使用
standalone="yes“
standalone=“no” 默认
如果你在XML文档里面写上gb2312,而在另存为时存为utf-8,那么会打不开。
因为gb2312是属于ANSI的,在中国它就代表的是GB2312,所以存为ANSI即可。
,如果想要存为UTF-8那么在XML中也要写成UTF-8.
u 明确一个概念
在xml中元素=标签=节点
u 在属性值有双引号和单引号的时候
“ " ‘ &aqot;
• 属性值用双引号(")或单引号(')分隔(如果属性值中有',用"分隔;有",用'分隔)
• 一个元素可以有多个属性,它的基本格式为:
<元素名属性名="属性值">
• 特定的属性名称在同一个元素标记中只能出现一次
• 属性值不能包括<,>, &
XML声明之前不能有注释
注释不能嵌套
有些内容可能不想让解析引擎解析执行,而是当作原始内容处理,用于把整段文本解释为纯字符数据而不是标记的情况。包含大量<、>、&或者"字符。CDATA节中的所有字符都会被当作元素字符数据的常量部分,而不是XML标记。
u 处理指令(了解)
html界面 css
xml 显示 css ,使用处理搞定
案例1:
my.css
name{
font-size: 100px;
font-weight: blod;
color: red;
}
sex{
font-size: 80px;
font-weight: blod;
color: blue;
}
age{
font-size: 50px;
font-weight: blod;
color: green;
}
在myClass.xml文件中使用
<?xml version="1.0"encoding="utf-8"?>
<?xml-stylesheet type="text/css"href="my.css"?>
<class>
<!--注释-->
<stu id='a0011'>
<name>杨过</name>
<sex>男</sex>
<age>20</age>
<介绍>aa</介绍>
<除毛净重>200</除毛净重>
</stu>
<stu id="a002">
<name>李莫愁</name>
<sex>女</sex>
<age>30</age>
</stu>
</class>
总结:
遵循如下规则的XML文档称为格式正规的XML文档:
l 语法规范
– XML声明语句
<?xml version="1.0"encoding="gb2312"?>
– 必须有且仅有一个根元素
– 标记大小写敏感
– 属性值用引号
– 标记成对
– 空标记关闭
– 元素正确嵌套
u 为什么需要dtd
去约束指定的XML文件。
l 常用的约束技术
• XML DTD
• XMLSchema
u 写dtd的注意事项
1. dtd文件要保存成 utf-8编码
要求:能够根据DTD写出XML文档。
u 校验xml的有效性(自己写一个HMTL文件,非常厉害)
1. 我们写一个 check.html文件,用于去校验load文件的有效性 (javascript(livescript) jscript(微软))
<html>
<head>
<scriptlanguage="javascript">
var xmldom= new ActiveXObject("Microsoft.XMLDOM");
xmldom.validateOnParse=true;
xmldom.load("myClass2.xml");
document.writeln("错误信息是:"+xmldom.parseError.reason);
document.writeln("错误行号:"+xmldom.parseError.line);
</script>
</head>
<body>
</body>
</html>
2. dtd文件时 myClass.dtd
<!ELEMENT 班级 (学生+)>
<!ELEMENT 学生 (名字,年龄,介绍)>
<!ELEMENT 名字 (#PCDATA)>
<!ELEMENT 年龄 (#PCDATA)>
<!ELEMENT 介绍 (#PCDATA)>
3. 我的对myClass.dtd写的xml文件myClass2.xml
<?xml version="1.0"encoding="utf-8" ?>
<!DOCTYPE 班级SYSTEM "myClass.dtd">
<班级>
<学生>
<名字>周星驰</名字>
<年龄>23</年龄>
<介绍>学习刻苦</介绍>
</学生>
<学生>
<名字>林青霞</名字>
<年龄>32</年龄>
<介绍>是一个好学生</介绍>
</学生>
</班级>
4. 如何把外部的dtd改成内部的dtd 比如 myClass2.xml修改成内部dtd去约束
<?xml version="1.0"encoding="utf-8" ?>
<!DOCTYPE 班级 [
<!ELEMENT 班级 (学生+)>
<!ELEMENT 学生 (名字,年龄,介绍)>
<!ELEMENT 名字 (#PCDATA)>
<!ELEMENT 年龄 (#PCDATA)>
<!ELEMENT 介绍 (#PCDATA)>
]>
<班级>
<学生>
<名字>周星驰</名字>
<年龄>23</年龄>
<介绍>学习刻苦</介绍>
</学生>
<学生>
<名字>林青霞</名字>
<年龄>32</年龄>
<介绍>是一个好学生</介绍>
</学生>
</班级>
引用DTD约束的两种方式。
l XML文件使用 DOCTYPE 声明语句来指明它所遵循的DTD文件,DOCTYPE声明语句有两种形式:
• 当引用的文件在本地时,采用如下方式:
<!DOCTYPE文档根结点 SYSTEM"DTD文件的URL">
例如: <!DOCTYPE 书架 SYSTEM “book.dtd”>。
• 当引用的文件是一个公共的文件时,采用如下方式:
<!DOCTYPE文档根结点 PUBLIC"DTD名称""DTD文件的URL">
例如:<!DOCTYPE web-app PUBLIC
"-//SunMicrosystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
u 属性的顺序问题
元素的顺序有要求,按照规定的顺序写,
属性的顺序没有要求.
属性的值,不能用数字开头.(就像javasrcriprt的id也不能以数字开头)
u 实体
实体分为:
引用实体,它是在dtd中定义的 <!ENTITYintro "这是一个好同志呀!">,可以放在dtd文件后,
该实体是在xml文件中使用, 具体是:
<介绍>学习刻苦&intro; &intro;</介绍>
参数实体
他在dtd中定义,并且在dtd中使用.
最后的myClass2.xml myClass.dtd check.html
myClass2.xml 内容
<?xml version="1.0"encoding="utf-8" ?>
<!DOCTYPE 班级 SYSTEM "myClass.dtd">
<班级>
<学生 学号="a123"性别="女" 大哥="a0002">
<名字>周星驰 &intro;</名字>
<年龄>23</年龄>
<介绍>学习刻苦 &intro; &intro;</介绍>
</学生>
<学生 住址="天津" 性别="男" 学号="a0002" 大哥="a0002 a0003">
<名字>林青霞</名字>
<年龄>32</年龄>
<介绍>&intro;是一个好学生</介绍>
</学生>
<学生 住址="大观园" 性别="男" 学号="a0003" 大哥="a0002">
<名字>贾宝玉</名字>
<年龄>16</年龄>
<介绍>是一个好学生 &intro;</介绍>
</学生>
</班级>
对应的 myClass.dtd文件
<!ELEMENT 班级 (学生+)>
<!ENTITY % tagname "名字">参数实体一定要放在它使用的前面。
<!ENTITY % tagname1 "名字gg">
<!ENTITY % tagname2 "名字kk">
<!ELEMENT 学生 (%tagname;,年龄,介绍)>
<!ATTLIST 学生
住址 CDATA #IMPLIED
学号 ID #REQUIRED
大哥 IDREFS #REQUIRED
性别 (男|女) #REQUIRED
公司 CDATA #FIXED "ibm"
>
<!ELEMENT %tagname; (#PCDATA)>
<!ELEMENT 年龄 (#PCDATA)>
<!ELEMENT 介绍 (#PCDATA)>
<!ENTITY intro "这是一个好同志呀!">
check.html文件内容
<html>
<head>
<script language="javascript">
var xmldom= newActiveXObject("Microsoft.XMLDOM");
xmldom.validateOnParse=true;
xmldom.load("myClass2.xml");
document.writeln("错误信息是:"+xmldom.parseError.reason);
document.writeln("错误行号:"+xmldom.parseError.line);
</script>
</head>
<body>
</body>
</html>
CATEGORY(HandTool|Table|Shop-Professional) "HandTool"
这种其实也在XMl中可写可不写的属性,写的话可以设置三种之一,不写的话,
在使用的时间,它会自己认为有这个属性,并且这个属性为默认值,十分重要。
PARTNUMCDATA #IMPLIED 这种是在XML中可写可不写的属性。
且记:在保存DTD的时间,要把它保存为UTF-8.
u 复杂的dtd的案例
1. 产品目录的dtd文件 product.dtd
<!ENTITY AUTHOR "John Doe">
<!ENTITY COMPANY "JD Power Tools,Inc.">
<!ENTITY EMAIL"[email protected]">
<!ELEMENTCATALOG (PRODUCT+)>
<!ELEMENT PRODUCT
(SPECIFICATIONS+,OPTIONS?,PRICE+,NOTES?)>
<!ATTLIST PRODUCT
NAME CDATA #IMPLIED
CATEGORY (HandTool|Table|Shop-Professional)"HandTool"
PARTNUM CDATA #IMPLIED
PLANT (Pittsburgh|Milwaukee|Chicago)"Chicago"
INVENTORY(InStock|Backordered|Discontinued) "InStock">
<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ATTLIST SPECIFICATIONS
WEIGHT CDATA #IMPLIED
POWER CDATA #IMPLIED>
<!ELEMENT OPTIONS (#PCDATA)>
<!ATTLIST OPTIONS
FINISH (Metal|Polished|Matte)"Matte"
ADAPTER (Included|Optional|NotApplicable)"Included"
CASE (HardShell|Soft|NotApplicable)"HardShell">
<!ELEMENT PRICE (#PCDATA)>
<!ATTLIST PRICE
MSRP CDATA #IMPLIED
WHOLESALE CDATA #IMPLIED
STREET CDATA #IMPLIED
SHIPPING CDATA #IMPLIED>
<!ELEMENT NOTES (#PCDATA)>
2. .针对 product.dtd写的 product.xml
<?xml version="1.0"encoding="utf-8"?>
<!DOCTYPE CATALOG SYSTEM"product.dtd">
<CATALOG>
<PRODUCT INVENTORY="InStock"NAME="冰箱"CATEGORY="Shop-Professional" PLANT="Chicago" >
<SPECIFICATIONS WEIGHT="50"POWER="100">
你好吗,这个不错!
</SPECIFICATIONS>
<OPTIONS FINISH="Polished"ADAPTER="NotApplicable" CASE="NotApplicable">
xxx
</OPTIONS>
<PRICE MSRP="123"WHOLESALE="20" STREET="90" SHIPPING="400">
</PRICE>
<NOTES>
xxx
</NOTES>
</PRODUCT>
</CATALOG>
XML解析API:
Jaxp(sun)、dom4j(这个效率更加高,不用学习jdom,因为很明显dom4j已经超越了jdom)
之所以学习jaxp它的效率是最低的,因为解析这个XML的标准是sun公司制定的,所以要学习它。
dom原理图.bmp
JAXP 开发包是J2SE的一部分,它由javax.xml、org.w3c.dom 、org.xml.sax包及其子包组成
在 javax.xml.parsers包中,定义了几个工厂类,程序员调用这些工厂类,可以得到对xml文档进行解析的 DOM 或 SAX的解析器对象。
DocumentBuilderFactory:定义工厂API,使应用程序能够从 XML 文档获取生成 DOM 对象树的解析器。
u dom技术(JAXP)注意,以下为用JAXP API 操作XML。
其实,JAXP的操作方式与JS对html的文档操作极为相似。
1. 所有的操作都是对myClass.xml的文件
<?xml version="1.0" encoding="utf-8" standalone="no"?><班级>
<学生sex="男">
<名字>周星驰</名字>
<年龄>43</年龄>
<介绍>学习刻苦</介绍>
</学生>
<学生sex="女">
<名字>林青霞</名字>
<年龄>32</年龄>
<介绍>是一个好学生</介绍>
</学生>
</班级>
2. 对文件进行遍历的代码
Dom中的所有节点都被看成一个Node,只是类型不同,有元素节点,文本节点,属性节点等。
在xml里面空白位置被当做文本节点处理。
publicstaticvoid list(Node node){
if(node.getNodeType()==Node.ELEMENT_NODE){
System.out.println("该节点名字是"+node.getNodeName());
}//排除空白节
NodeList nl=node.getChildNodes();
//遍历所有的子节点
for(inti=0;i<nl.getLength();i++){
Nodenode2=nl.item(i);
list(node2);
}
}
3. 读取某一个节点
//读取第一个学生的名字.
publicstaticvoid read(Document doc){
//1.得到根元素 Element 是 Node 子类,它的能力比Node 强,
Element e=doc.getDocumentElement();
//2.得到学生节点对象,它的返回是一个node,是element的父类,也就是从大向小的转,所以要强转,如果从小向大转不用强制转换。
Element name=(Element)e.getElementsByTagName("名字").item(1);
System.out.println(name.getTextContent());
}
4. 读取属性
//读取属性
publicstaticvoid readAttr(Document doc){
//得的根元素
Element root=doc.getDocumentElement();
//得到第二个学生节点对象
Element stu2=(Element) root.getElementsByTagName("学生").item(1);
String sexVal=stu2.getAttribute("sex");
System.out.println(sexVal);
}
5. 添加学生
//添加节点(添加学生)
publicstaticvoid addNode(Document doc) throwsTransformerException{
//创建一个元素节点. Element Node
Element stu=doc.createElement("学生");
Element name=doc.createElement("名字");
name.setTextContent("贾宝玉");
stu.appendChild(name);
//把stu 挂到根元素下
doc.getDocumentElement().appendChild(stu);
//更新文档,因为以上只是在内存中改变了。所以要更新到硬盘上。
//1.得打TransformerFactory
TransformerFactorytff=TransformerFactory.newInstance();
//2.得到一个转化器
Transformer tf=tff.newTransformer();
//3.转化
tf.transform(new DOMSource(doc), new StreamResult(new File("src/myClass.xml")));
}
6. 给某个元素添加属性
publicstaticvoid addAttribute(Document doc) throws Exception{
//得到第三个学生的节点对象
Element e=(Element)doc.getElementsByTagName("学生").item(2);
e.setAttribute("sex", "男");//添加属性
//这是添加属性的第二种方法.
// Attratt=doc.createAttribute("sex2");
// att.setTextContent("女");
// e.setAttributeNode(att);
//更新
TransformerFactorytff=TransformerFactory.newInstance();
Transformer tf=tff.newTransformer();
tf.transform(new DOMSource(doc), new StreamResult(new File("src/myClass.xml")));
}
7. 删除节点
//删除一个学生
publicstaticvoid delNode(Document doc) throwsException{
//得到第三个学生的节点对象
Element e=(Element)doc.getElementsByTagName("学生").item(2);
//doc.getDocumentElement().removeChild(e);
//我们在删除某个节点的时候,可以通过得打其父节点,然后将其删除.
e.getParentNode().removeChild(e);
TransformerFactorytff=TransformerFactory.newInstance();
Transformer tf=tff.newTransformer();
tf.transform(new DOMSource(doc), new StreamResult(new File("src/myClass.xml")));
}
8. 更新元素的内容
//修改学生信息把周星驰的年龄在原来的基础+10;
publicstaticvoid updNode(Document doc) throwsException{
//得学生
Element e=(Element) doc.getElementsByTagName("年龄").item(0);
//取出年龄的值
String age=e.getTextContent();
int newAge=Integer.parseInt(age)+10;
e.setTextContent(newAge+"");
//更新xml
TransformerFactorytff=TransformerFactory.newInstance();
Transformer tf=tff.newTransformer();
tf.transform(new DOMSource(doc), new StreamResult(new File("src/myClass.xml")));
}