Extensible Markup Language
,可扩展标记语言。与HTML的比较
XML用途
如:
如:
三要素:
XML声明
说明XML文档的基本信息,包括版本号与字符集,写在XML的第一行。
如:
version
:表示版本号1.0encoding UTF-8
:设置字符集,用于支持中文第一个XML文件
<hr>
<employee no="3309">
<name>张三name>
<age>31age>
<salary>4000salary>
<department>
<dname>会计部dname>
<address>XX大厦-A01address>
department>
employee>
<employee no="3310">
<name>李四name>
<age>30age>
<salary>3000salary>
<department>
<dname>工程部dname>
<address>XX大厦-A02address>
department>
employee>
hr>
在浏览器中显示:
如果写错了:
合法的标签名
-
分隔合理使用属性
如:
处理特殊字符
<
、>
特殊字符,会破坏文档结构如:
解决方案:
XML支持的五种实体引用
CDATA标签
开始,到]]
结束
有序的子元素
DTD
与XML Schema
.dtd
例子:
<!ELEMENT hr(employee)>
<!ELEMENT employee(name,age,salary,department)>
<!ELEMENT name(#PCDATA)>
DTD定义节点数量
如某个子节点需要多次重复出现,则需要在子节点后增加相应的描述符。
<!ELEMENT hr(employee+)>
<!ELEMENT hr(employee*)>
<!ELEMENT hr(employee?)>
XML引用DTD文件
在XML中使用标签来引用DTD文件。
格式:
DOCTYPE 根节点 SYSTEM "dtd文件路径">
第一个dtd文件
hr.xml:
DOCTYPE hr SYSTEM "hr.dtd">
<hr>
<employee no="3309">
<name>张三name>
<age>31age>
<salary>4000salary>
<department>
<dname>会计部dname>
<address>XX大厦-A01address>
department>
employee>
<employee no="3310">
<name>李四name>
<age>30age>
<salary>3000salary>
<department>
<dname>工程部dname>
<address>XX大厦-A02address>
department>
employee>
hr>
对应的dtd:
<!ELEMENT hr (employee+)>
<!ELEMENT employee (name,age,salary,department)>
<!ATTLIST employee no CDATA "">
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT salary (#PCDATA)>
<!ELEMENT department (dname,address)>
<!ELEMENT dname (#PCDATA)>
<!ELEMENT address (#PCDATA)>
.xsd
写xsd的时候遇到了一些困难,记录一下解决的办法:eclipse写xsd报错:s4s-elt-schema-ns: The namespace of element…且没有自动补全类提示 问题的解决方法
xml文件对xsd的引入:
<hr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="hr1.xsd">
xsd文件:
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="hr">
<complexType>
<sequence>
<element name="employee" minOccurs="1" maxOccurs="9999">
<complexType>
<sequence>
<element name="name" type="string">element>
<element name="age">
<simpleType>
<restriction base="integer">
<minInclusive value="18">minInclusive>
<maxInclusive value="50">maxInclusive>
restriction>
simpleType>
element>
<element name="salary" type="integer">element>
<element name="department">
<complexType>
<sequence>
<element name="dname" type="string">element>
<element name="address" type="string">element>
sequence>
complexType>
element>
sequence>
<attribute name="no" type="string" use="required">attribute>
complexType>
element>
sequence>
complexType>
element>
schema>
DOM,即Document Object Model,定义了访问和操作XML文档的标准方法,DOM把XML文档作为树结构来查看,能够通过DOM树来读写所有元素。
如:
下载Dom4j:下载地址
在src下创建一个Foler,命名为lib。把下载的Dom4j拖进去。
然后:
若出现了一个新的dom4j就成功了。
尝试一下:
xml文件为:
<hr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="hr1.xsd">
<employee no="3309">
<name>张三name>
<age>31age>
<salary>4000salary>
<department>
<dname>会计部dname>
<address>XX大厦-A01address>
department>
employee>
<employee no="3310">
<name>李四name>
<age>30age>
<salary>3000salary>
<department>
<dname>工程部dname>
<address>XX大厦-A02address>
department>
employee>
hr >
java文件为:
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class HrReader {
public void readXml() {
//hr.xml的地址
// String file="D:\\eclipse\\xml\\src\\hr.xml"; //这样也可以
String file="D:/eclipse/xml/src/hr.xml";
//SAXReader类是读取XML文件的核心类。用于将XML解析后以"树"的形式保存在内存中
SAXReader reader=new SAXReader();
//解析
try {
Document document=reader.read(file);
//获取XML文档的根节点,即hr标签
Element root=document.getRootElement();
//获取所有employee标签
List<Element> employee =root.elements("employee");
//遍历
for(Element e:employee) {
//element方法用于获取唯一的子节点对象
Element name=e.element("name");
//获取标签的文本值
String empName=name.getText();
System.out.println(empName);
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
HrReader reader=new HrReader();
reader.readXml();
}
}
输出:
张三
李四
若把Element name=e.element("name");
的name改成age,则输出:
31
30
可以把这三句合并:
//element方法用于获取唯一的子节点对象
Element name=e.element("name");
//获取标签的文本值
String empName=name.getText();
System.out.println(empName);
合并为:
System.out.println(e.elementText("name"));
如果想要获得属性:
for(Element e:employee) {
//element方法用于获取唯一的子节点对象
Element name=e.element("name");
//获取属性no
Attribute att=e.attribute("no");
System.out.println(att.getText());
}
输出:
3309
3310
如何利用Dom4j往XML里写数据呢?用addElement
方法创建新节点。
我们想给XML加一个新的节点:
增加新节点的代码:这只是在内存中增加新节点,我们稍后还要把它写进XML
Document document=reader.read(file);
Element root=document.getRootElement();
//用addElement方法创建新的employee节点
Element employee=root.addElement("employee");
//增加属性
employee.addAttribute("no", "3311");
//新节点的姓名
Element name=employee.addElement("name");
name.setText("王五");
//年龄
employee.addElement("age").setText("25");
//工资
employee.addElement("salary").setText("3600");
//办公地点
Element department=employee.addElement("department");
department.addElement("dname").setText("人事部");
department.addElement("address").setText("XX大厦-A03");
写进XML的代码:
Writer writer=new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
document.write(writer);
writer.close();
总体代码:
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class HrWriter {
public void writeXML() {
//获取XML文件路径
String file="D:/eclipse/xml/src/hr.xml";
//对XML文件读取和解析
SAXReader reader=new SAXReader();
try {
Document document=reader.read(file);
Element root=document.getRootElement();
//用addElement方法创建新的employee节点
Element employee=root.addElement("employee");
//增加属性
employee.addAttribute("no", "3311");
//新节点的姓名
Element name=employee.addElement("name");
name.setText("王五");
//年龄
employee.addElement("age").setText("25");
//工资
employee.addElement("salary").setText("3600");
//办公地点
Element department=employee.addElement("department");
department.addElement("dname").setText("人事部");
department.addElement("address").setText("XX大厦-A03");
//以上这一段只是在内存中进行编写
//以下是把这些写入XML中
//把文件输出流转成writer对象
try {
Writer writer=new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
document.write(writer);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
HrWriter hrWriter=new HrWriter();
hrWriter.writeXML();
}
}
结果,hr.xml中增加了:
<employee no="3311">
<name>王五name>
<age>25age>
<salary>3600salary>
<department>
<dname>人事部dname>
<address>XX大厦-A03address>
department>
employee>
基本表达式
相关案例:
谓语表达式
使用中括号[]再加一个谓语来说明。
下载Jaxen:阿里云云效 Maven
在这里搜Jaxen即可。
我下载的是这个:
我们把下载好的jar包复制到lib下,然后:
现在我们用XPath进行查询。
hr.xml文件改一下,多增加一点员工:
DOCTYPE hr SYSTEM "hr.dtd">
<hr>
<employee no="3301">
<name>李铁柱name>
<age>37age>
<salary>3600salary>
<department>
<dname>人事部dname>
<address>XX大厦-B105address>
department>
employee>
<employee no="3302">
<name>林海name>
<age>50age>
<salary>7000salary>
<department>
<dname>财务部dname>
<address>XX大厦-B106address>
department>
employee>
<employee no="3303">
<name>安娜name>
<age>24age>
<salary>4600salary>
<department>
<dname>人事部dname>
<address>XX大厦-B105address>
department>
employee>
<employee no="3304">
<name>张晓宇name>
<age>29age>
<salary>3000salary>
<department>
<dname>后勤部dname>
<address>XX大厦-B108address>
department>
employee>
<employee no="3305">
<name>赵子轩name>
<age>19age>
<salary>1500salary>
<department>
<dname>后勤部dname>
<address>XX大厦-B108address>
department>
employee>
<employee no="3306">
<name>张晓璇name>
<age>20age>
<salary>1700salary>
<department>
<dname>后勤部dname>
<address>XX大厦-B108address>
department>
employee>
<employee no="3307">
<name>张檬name>
<age>43age>
<salary>8700salary>
<department>
<dname>会计部dname>
<address>XX大厦-B103address>
department>
employee>
<employee no="3308">
<name>李梅name>
<age>33age>
<salary>8700salary>
<department>
<dname>工程部dname>
<address>XX大厦-B104address>
department>
employee>
<employee no="3309">
<name>张三name>
<age>31age>
<salary>4000salary>
<department>
<dname>会计部dname>
<address>XX大厦-B103address>
department>
employee>
<employee no="3310">
<name>李四name>
<age>23age>
<salary>3000salary>
<department>
<dname>工程部dname>
<address>XX大厦-B104address>
department>
employee>
hr>
用XPath的例子:这里的XPath表达式是/hr/employee
,即要根节点下的所有employee,输出所有employee节点的name、age、salary:
public class XPathTestor {
// 参数:传入的XPath表达式
public void xpath(String xpathExp) {
String file = "D:/eclipse/xml/src/hr2.xml";
SAXReader reader = new SAXReader();
try {
Document document = reader.read(file);
// 接下来是执行XPath的核心方法selectNodes
// Node是节点Element和标签Attribute的父类,是selectNodes返回的数据类型
// selectNodes返回的是一个List
List<Node> nodes = document.selectNodes(xpathExp);
// 对List进行遍历
for (Node node : nodes) {
Element emp = (Element) node;
// 打印name
System.out.println(emp.elementText("name"));
System.out.println(emp.elementText("age"));
System.out.println(emp.elementText("salary"));
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
public static void main(String[] agrs) {
XPathTestor testor = new XPathTestor();
// 想要所有的employee节点。其中hr是根节点。
String str = "/hr/employee";
testor.xpath(str);
}
}
输出:
李铁柱
37
3600
林海
50
7000
安娜
24
4600
张晓宇
29
3000
赵子轩
19
1500
张晓璇
20
1700
张檬
43
8700
李梅
33
8700
张三
31
4000
李四
23
3000
就是这样。
关于XPath表达式:
/hr/employee
//employee
/hr/employee[salary<4000]
或//employee[salary<4000]
代进去,输出得:
李铁柱
张晓宇
赵子轩
张晓璇
李四
//employee[name="李铁柱"]
//employee[@no="3301"]
//employee[1]
——表示第一个出现的employee//employee[position()<6]
代入得:
李铁柱
林海
安娜
张晓宇
赵子轩
XPath支持组合表达式:如果想要第3和8名员工,可以://employee[3] | //employee[8]
,竖线|
表示把前后两个合并。
代入得:
安娜
李梅