XML:软件的配置文件,数据的载体(小型的“数据库”)
2)xml标签名称区分大小写
4)xml标签名中间不能使用空格
5)xml标签名不能以数字开头
6)注意: 在一个xml文档中,只有一个根标签
7)属性值必须以引号包含,不能单双引号
8)cdata块 :可以让一些需要进行包含特殊字符的内容统一进行原样输出
//tomcat temp临时目录 work是tomcat 的运行目录,jsp运行产生的临时文件放在这里
XML解析方式:
1、DOM解析 Dom4J
2、SAX解析
DOM解析:
xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一颗Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容
1、读取 contactInfo.xml 的内容
<?xml version="1.0" encoding="utf-8"?>
<!-- encoding 与 文件保存的编码格式一样 -->
<contactList>
<contact flg="true" id="001" >
<name>Mr.L</name>
<age>21</age>
<phone>
啊啊啊
<length>11</length>
<number>13900</number>
</phone>
</contact>
<contact id="002">
<name>小明</name>
<age>22</age>
<phone>138000</phone>
</contact>
<![CDATA[
这里的内容原样输出 , <p>不会被当作xml标签进行解析</p>
]]>
</contactList>
public class demo {
public static void main(String[] args) {
try {
SAXReader reader=new SAXReader();//dom4j 创建xml解析器
Document doc=reader.read(new File("./src/contactInfo.xml"));// ./ 项目名称
//eclipse 中 选中上面两行,右键 surround with tryCatch block
//System.out.println(doc);
//.element("name") 获取子标签中 第一个名称为name的节点
//.nodeIterator(): 得到当前节点下的所有子节点对象(不包含孙以下的节点)
Iterator<Node> iter=doc.getRootElement().element("contact").nodeIterator();
while(iter.hasNext()){
System.out.println(iter.next().getName());
//属性id="001" 和 文本 小明 也是 节点,但不是 标签节点 ,无法调用getName(),返回null
}
} catch (DocumentException e) {
e.printStackTrace();
throw new RuntimeException(e);//出现异常 停止运行
}
}
@Test
public void test() throws Exception{
SAXReader reader=new SAXReader();//dom4j 创建xml解析器
Document doc=reader.read(new File("./src/contactInfo.xml"));// ./ 项目名称
//getChildNodes(doc.getRootElement());//标签
StringBuffer sb=new StringBuffer();
getChildNodes(doc.getRootElement(),sb);
System.out.println(sb.toString());
/* 文本
* Element contactOne=doc.getRootElement().element("contact");
* Element contactOne=doc.getRootElement().element("contact");
System.out.println(contactOne.element("name").getText());
System.out.println(contactOne.elementText("phone").trim());//空格和换行也是xml的内容
*/
/* 属性
Element contactOne=doc.getRootElement().element("contact");
Attribute attr=contactOne.attribute("id");
System.out.println(attr.getName()+" "+attr.getValue());
System.out.println(contactOne.attributeValue("id"));
List<Attribute> list=contactOne.attributes();
for(Attribute attr:list){
System.out.println(attr.getName()+" "+attr.getValue());
}
Iterator<Attribute> iter=contactOne.attributeIterator();
while(iter.hasNext())
{ Attribute attr=iter.next();
System.out.println(attr.getName()+" "+attr.getValue());
}
*/
}
//获取 标签下的所有 标签
private void getChildNodes(Element element){
System.out.println(element.getName());
/* Iterator<Node> iter=element.nodeIterator();
while(iter.hasNext()){
Node node=iter.next();
if(node instanceof Element){
getChildNodes((Element)node);
}
}*/
List<Element> list=element.elements();//获取所有子标签
for(Element elt:list){
getChildNodes(elt);
}
}
private void getChildNodes(Element elm,StringBuffer sb){
sb.append("<"+elm.getName());
List<Attribute> list=elm.attributes();
if(list!=null){
for(Attribute attr:list){
sb.append(" "+attr.getName()+"=\""+attr.getValue()+"\"");
}
}
sb.append(">");
Iterator<Node> iter=elm.nodeIterator();
while(iter.hasNext()){
Node node=iter.next();
if(node instanceof Element){
getChildNodes((Element)node,sb);
}
if(node instanceof Text){
sb.append(((Text)node).getText());
}
}
sb.append("</"+elm.getName()+">");
}
/*
* 实用 的方法
*/
public void xmlToClass() throws Exception{
List<Contact> list=new ArrayList<Contact>();
SAXReader reader=new SAXReader();
Document doc=reader.read(new File("./src/contactInfo.xml"));
Iterator<Element> iter=doc.getRootElement().elementIterator("contact");
//element.elementIterator("标签名");// 指定名称的所有子标签
while(iter.hasNext()){
Element elm=iter.next();
Contact contact=new Contact();
contact.setId(elm.attributeValue("id"));
contact.setName(elm.elementText("name"));
list.add(contact);
}
for(Contact contact:list){
System.out.println(contact);
}
}
}
2、修改或生成xml
/**
* 1.生成指定内容的xml文档
* @throws Exception
*/
@Test
public void test1() throws Exception{
//1.内存创建xml文档
Document doc = DocumentHelper.createDocument();
//2.写入内容
Element rootElem = doc.addElement("Students");
//2.1 增加标签
Element studentElem1 = rootElem.addElement("Student");
//2.2 增加属性 或 修改属性(同名覆盖)
studentElem1.addAttribute("id", "1");
//2.3 增加标签,同时设置文本
studentElem1.addElement("name").setText("张三");
studentElem1.addElement("gender").setText("男");
studentElem1.addElement("grade").setText("计算机1班");
studentElem1.addElement("address").setText("广州天河");
//2.1 增加标签
Element studentElem2 = rootElem.addElement("Student");
//2.2 增加属性
studentElem2.addAttribute("id", "2");
//2.3 增加标签,同时设置文本
studentElem2.addElement("name").setText("李四");
studentElem2.addElement("gender").setText("女");
studentElem2.addElement("grade").setText("计算机2班");
studentElem2.addElement("address").setText("广州越秀");
//node.detach(); 删除
//3.内容写出到xml文件
//3.1 输出位置
FileOutputStream out = new FileOutputStream("e:/student.xml");
//3.2 指定格式
OutputFormat format = OutputFormat.createPrettyPrint();
//OutputFormat format = OutputFormat.createCompactFormat(); //紧凑的格式.去除空格换行.项目上线的时候
// 设置编码
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
//3.3 写出内容
writer.write(doc);
//3.4关闭资源
writer.close();
}
3、XPath 是在 XML 文档中通过元素和属性进行查找信息的语言, 当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦
jaxen-1.1-beta-6.jar
List<Node> selectNodes(String xpathExpression)
Node selectSingleNode(String xpathExpression) //返回一个Node对象或多个中的第一个对象
语法: 选取节点 使用限定语 使用通配符
/ 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)
// 相对路径 表示不分任何层次结构的选择元素。
* 通配符 表示匹配所有元素
[] 条件 表示选择什么条件下的元素
@ 属性 表示选择属性节点
and 关系 表示条件的与关系(等价于&&)
text() 文本 表示选择文本内容
Element stuElem = (Element)doc.selectSingleNode("//Student[@id='2']");//1.查询id为2的学生标签
String xpath = "";
/**
* 1. / 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)
*/
xpath = "/contactList";
xpath = "/contactList/contact";
/**
* 2. // 相对路径 表示不分任何层次结构的选择元素。
*/
xpath = "//contact/name";
xpath = "//name";
/**
* 3. * 通配符 表示匹配所有元素
*/
xpath = "/contactList/*"; //根标签contactList下的所有子标签
xpath = "/contactList//*";//根标签contactList下的所有标签(不分层次结构)
/**
* 4. [] 条件 表示选择什么条件下的元素
*/
//带有id属性的contact标签
xpath = "//contact[@id]";
//第二个的contact标签
xpath = "//contact[2]";
//选择最后一个contact标签
xpath = "//contact[last()]";
/**
* 5. @ 属性 表示选择属性节点
*/
xpath = "//@id"; //选择id属性节点对象,返回的是Attribute对象
xpath = "//contact[not(@id)]";//选择不包含id属性的contact标签节点
xpath = "//contact[@id='002']";//选择id属性值为002的contact标签
xpath = "//contact[@id='001' and @name='eric']";//选择id属性值为001,且name属性为eric的contact标签
/**
*6. text() 表示选择文本内容
*/
//选择name标签下的文本内容,返回Text对象
xpath = "//name/text()";
xpath = "//contact/name[text()='张三']";//选择姓名为张三的name标签
List<Node> list = doc.selectNodes(xpath);
for (Node node : list) {
System.out.println(node);
}
public static void main(String[] args)throws Exception{
//1.获取用户输入的用户名和密码
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名:");
String name = br.readLine();
System.out.println("请输入密码:");
String password = br.readLine();
//2.到“数据库”中查询是否有对应的用户
//对应的用户: 在user.xml文件中找到一个
//name属性值为‘用户输入’,且password属性值为‘用户输入’的user标签
Document doc = new SAXReader().read(new File("./src/user.xml"));
Element userElem = (Element)doc.selectSingleNode("//user[@name='" +name +"' and @password='"+password+"']");
if(userElem!=null){
//登录成功
System.out.println("登录成功");
}else{
//登录失败
System.out.println("登录失败");
}
DOM解析 | SAX解析(跳过) |
原理: 一次性加载xml文档,不适合大容量的文件读取 | 原理: 加载一点,读取一点,处理一点。适合大容量文件的读取 |
DOM解析可以任意进行增删改成 | SAX解析只能读取 |
DOM解析任意读取任何位置的数据,甚至往回读 | SAX解析只能从上往下,按顺序读取,不能往回读 |
DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。 | SAX解析基于事件的编程方法。java开发编码相对复杂。 |