Jsp 复习材料一: XML解析
1.xml
1.规范:
- 所有的XML文件都应该有结束标签
- 便签大小写有区别,并且前后要一致
- 规定XML只有一个根节点元素
- 属性值必须加引号,可通过节点加getAttributes()。获得属性对象
- 特殊字符需要转义
- 解析时空格和回车换行会被保留
2.XML和HTML的差异
XML是对HTML的补充,即对数据进行存储和传输,可自行定义标签,不能通过浏览器显示,区别于HTML。
3.命名规范
- 名称可以含字母、数字以及其他的字符
- 名称不能以数字或者标点符号开始
- 名称不能以字符 “xml”(或者 XML、Xml)开始
- 名称不能包含空格
- 可使用任何名称,没有保留的字词
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE java1705 [
<!ELEMENT java1705 (student+)>
<!ELEMENT student (name,age,sex,height)>
<!ATTLIST student id CDATA "10086">
<!ATTLIST student user CDATA "jack">
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ELEMENT height (#PCDATA)>
]>
//DTD约束
<java1705>
<student id="1001" user="zhangsan">
<name>张三</name>
<age>19</age>
<sex>男</sex>
<height>180</height>
</student>
<student id="1002" user="lisi">
<name>李四</name>
<age>21</age>
<sex>男</sex>
<height>178</height>
</student>
<student id="1003" user="wangwu">
<name>王五</name>
<age>22</age>
<sex>男</sex>
<height>182</height>
</student>
</java1705>
2.xml解析
2.1 DOM解析
1.特点
W3C认可的规范。适合于小型文件。基于树形结构。非一次性处理,简单。
2.代码:
public class DOM4jParse {
public static void main(String[] args) {
try {
///创建 XML 的DOM4J解析器
SAXReader saxReader = new SAXReader();
//解析XML文件
Document document = saxReader.read(new File("student.xml"));
//得到根节点
Element rootElement = document.getRootElement();
//得到根节点的所有子元素节点
List<Element> elements = rootElement.elements();
ArrayList<Student> list = new ArrayList<>();
for (int i=0;i<elements.size();i++){
Element element = elements.get(i);
//获取属性值
String id = element.attributeValue("id");//得到节点内队形属性名的值
String user = element.attributeValue("user");
// Element name = element.element("name");//得到element节点下的name子元素子节点
// String text = name.getText();
String name = element.elementText("name");//得到节点的内容
String age = element.elementText("age");
String sex = element.elementText("sex");
String height = element.elementText("height");
list.add(new Student(id,user,name,age,sex,height));
}
for (int i=0;i<list.size();i++){
Student student = list.get(i);
System.out.println(student.toString());
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
2.2 SAX解析
1.特点
- 边读边解析,应用于大型XML文档
- 解决内存问题,不需每次都访问内存
- 事件驱动,文档读入过程就是SAX的解析过程,基于回调机制的程序运行方法
- 只支持读、访问效率低、只能顺序访问
2.代码:
public class SAXParse {
public static void main(String[] args) {
try {
//NO.1 创建解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//NO.2 通过解析工厂,创建解析构造器
SAXParser saxParser = factory.newSAXParser();
//No.3 指定解析的文件,并指定解析规则(DefaultHandler)
MyHandler myHandler = new MyHandler();
saxParser.parse(new File("student.xml"), myHandler);
//解析结束
ArrayList<Student> list = myHandler.getList();
for (int i = 0; i < list.size(); i++) {
Student student = list.get(i);
System.out.println(student.toString());
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* SAX 解析过程处理器
*/
private static class MyHandler extends DefaultHandler {
ArrayList<Student> list = new ArrayList<>();
public ArrayList<Student> getList() {
return list;
}
private Student student;
@Override
public void startDocument() throws SAXException {
System.out.println("开始解析内容");
}
/**
* 解析到开始标签
*
* @param uri 命名空间
* @param localName 不支持
* @param qName [返回前缀:]标签名字(如果没有命名空间,返回标签名)
* @param attributes 该标签的所有属性对象
* @throws SAXException
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// System.out.println("<"+qName);
if ("student".equals(qName)) {
student = new Student();
String id = attributes.getValue("id");
String user = attributes.getValue("user");
student.setId(Integer.parseInt(id));
student.setUser(user);
}
target = qName;
}
//为了在characters方法中取出有效的字符内容,标记开始节点的名字
private String target = null;
/**
* 解析到字符串内容(空格,回车,文字)
*
* @param ch 文档缓存在内存中的内容,长度为8192
* @param start 遇到的文本内容在缓存中的位置,
* @param length 文本内容到下一个元素节点的长度
* @throws SAXException
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String content = new String(ch, start, length);
// System.out.println(content);
switch (target) {
case "name":
student.setName(content);
break;
case "age":
student.setAge(Integer.parseInt(content));
break;
case "sex":
student.setSex(content);
break;
case "height":
student.setHeight(content);
break;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("student".equals(qName)) {
list.add(student);
}
target = null;//为了防止结束节点之后取出的无效字符再次赋值给student,所以重置target
}
@Override
public void endDocument() throws SAXException {
System.out.println("解析结束");
}
}
}
2.3JDOM解析
1.特点
- 基于树形结构,利用纯java技术对XML文档进行解析,它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。
- 具有SAX的java规则
- 没有向下兼容的限制,比DOM简单
- 不过不能处理大于内存的文档。
- 针对实例文档不提供DTD与模式的任何实际模型。
- 不支持与DOM中相应遍历包
2.代码
public class JdomParse {
public static void main(String[] args) {
try {
//NO.1 创建jDOM 解析构造器
SAXBuilder saxBuilder = new SAXBuilder();
//NO.2 解析整个XML文档
org.jdom2.Document build = saxBuilder.build(new File("student.xml"));
Element rootElement = build.getRootElement();//得到根节点
List<Element> children = rootElement.getChildren();//获取元素节点下的所有子元素节点
ArrayList<Student> list = new ArrayList<>();
for(int i=0;i<children.size();i++){
Element element = children.get(i);
String id = element.getAttributeValue("id");
String user = element.getAttributeValue("user");
System.out.println(" "+id+" "+user);
//获取element元素下的name子元素节点
// Element name = element.getChild("name");
// String text = name.getText();//取出元素内容
String name = element.getChildText("name");
String age = element.getChildText("age");
String sex = element.getChildText("sex");
String height = element.getChildText("height");
list.add(new Student(id,user,name,age,sex,height));
}
for (int i=0;i<list.size();i++){
Student student = list.get(i);
System.out.println(student.toString());
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.4DOM4j解析(重点掌握)
1.特点
- 提供了构建文档表示的选项,它通过DOM4J API和标准DOM接口具有并行访问功能。
- 使用Collections类,灵活
- 一个简单、灵活的开放源代码的库、
- 与JDOM不同的是,dom4j使用接口和抽象的人分离出来而后独立基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
2.代码
public class DOM4jParse {
public static void main(String[] args) {
try {
///创建 XML 的DOM4J解析器
SAXReader saxReader = new SAXReader();
//解析XML文件
Document document = saxReader.read(new File("student.xml"));
//得到根节点
Element rootElement = document.getRootElement();
//得到根节点的所有子元素节点
List<Element> elements = rootElement.elements();
ArrayList<Student> list = new ArrayList<>();
for (int i=0;i<elements.size();i++){
Element element = elements.get(i);
//获取属性值
String id = element.attributeValue("id");//得到节点内队形属性名的值
String user = element.attributeValue("user");
// Element name = element.element("name");//得到element节点下的name子元素子节点
// String text = name.getText();
String name = element.elementText("name");//得到节点的内容
String age = element.elementText("age");
String sex = element.elementText("sex");
String height = element.elementText("height");
list.add(new Student(id,user,name,age,sex,height));
}
for (int i=0;i<list.size();i++){
Student student = list.get(i);
System.out.println(student.toString());
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
3.比较
- DOM4J性能最好,连Sun的JAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.
- JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM。虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。
- SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。