<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="1">
<name>鲁宾逊漂流记</name>
<author>丹尼尔·笛福</author>
<year>2014</year>
<price>89</price>
</book>
<book id="2">
<name>老人与海</name>
<year>2004</year>
<price>77</price>
<language>English</language>
</book>
</bookstore>
例如对该XML文件进行解析
1. DOM
- DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准
- 不仅能读,还能修改,而且能够实现随机访问,缺点是解析速度慢,适合解析小型文档
- 一般应用于小型的配置XML,方便操作
- 为载入到内存的文档节点建立类型描述,呈现可横向移动、潜在巨大的树型结构
- 当xml文件较大时,对内存消耗比较大,容易影响解析性能并造成内存溢出
准备工作:
1..创建一个DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2..创建一个DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
3..通过DocumentBuilder的parse方法加载book.xml文件到当前项目下
Document document = db.parse("book.xml");
开始解析:
1..获取到所有的book节点
NodeList bookList = document.getElementsByTagName("book");
2..通过bookList.getLength()可以获取到book节点的个数,通过bookList.item(index)可以对指定的book节点进行操作,从而遍历每个book节点的子节点
Node book = bookList.item(i); //省略for循环
3..获取book节点的所有属性集合(这里book只有 id 这一个属性)
NamedNodeMap attrs = book.getAttributes();
4..遍历book的属性
for (int j = 0; j < attrs.getLength(); j++) {
//通过item(index)方法获取book节点的某一个属性
Node attr = attrs.item(j);
//获取属性名
System.out.println("属性名:" + attr.getNodeName());
//获取属性值
System.out.println("属性值" + attr.getNodeValue());
}
也可以直接通过’id’获取到其值
String attrValue = book.getAttribute("id");
5..解析book节点的子节点,获取子节点列表
NodeList childNodes = book.getChildNodes();
6..遍历子节点列表,获取节点名和节点值
for (int k = 0; k < childNodes.getLength(); k++) {
//区分出text类型的node以及element类型的node
if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
//获取element类型节点的节点名
System.out.print("第" + (k + 1) + "个节点的节点名:" + childNodes.item(k).getNodeName());
//获取element类型节点的节点值
System.out.println("--节点值是:" +childNodes.item(k).getFirstChild().getNodeValue());
//也可以通过getTextContent()获取节点值
//System.out.println("--节点值是:" + childNodes.item(k).getTextContent());
}
}
对于该XML文件来说
每对标签都是一个节点,id是属性,每个换行是一个text,所以book的子节点列表的长度为9
2. SAX
- 只能读,不能修改,只能顺序访问,适合解析大型XML,解析速度快
- 采用事件驱动模式,对内存消耗比较小
- 常应用于处理大量数据的XML,实现异构系统的数据访问,实现跨平台
- 从文档的开始通过每一节点移动,定位一个特定的节点
- 适用于只需要处理xml中数据时
SAXTest.java
public class SAXTest {
public static void main(String[] args) {
//获取SAXParserFactory的实例
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
//通过factory获取SAXParser实例
SAXParser parser = factory.newSAXParser();
//加载book.xml文件到当前项目下
parser.parse("books.xml", new SAXParseHandle());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
parse方法第二个参数是一个handle对象实例,这里需要创建一个类,该类继承DefaultHandler类,并通过重写该类的方法来定义解析规则
SAXParseHandle.java
public class SAXParseHandle extends DefaultHandler {
ArrayList<Book> bookList = new ArrayList<Book>();
Book book = null;
String value = null;
//用来标识解析开始
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("sax解析开始.......");
}
//用来标识解析结束
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("sax解析结束.......");
}
//用来遍历XML文件的开始标签
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if(qName.equals("book"))
{
book = new Book();
//已知book属性名的情况下
//System.out.println("id="+attributes.getValue("id"));
//不知道book属性名的情况下
for(int i = 0;i < attributes.getLength();i++) {
System.out.println(attributes.getQName(i)+"--"+attributes.getValue(attributes.getQName(i)));
if (attributes.getQName(i).equals("id")) {
book.setId(attributes.getValue(i));
}
}
}else if(!qName.equals("bookstore")&&!qName.equals("book")) {
System.out.print(qName+"--");
}
}
//用来遍历XML文件的结束标签
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if (qName.equals("book")) {
bookList.add(book);
book = null;
System.out.println("======================结束遍历某一本书的内容=================");
}
else if (qName.equals("name")) {
book.setName(value);
}
else if (qName.equals("author")) {
book.setAuthor(value);
}
else if (qName.equals("year")) {
book.setYear(value);
}
else if (qName.equals("price")) {
book.setPrice(Integer.parseInt(value));
}
else if (qName.equals("language")) {
book.setLanguage(value);
}
}
//用来获取标签间的文本
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
value = new String(ch,start,length);
if(!value.trim().equals("")) //去掉空格后不为空
System.out.println(value);
}
public ArrayList<Book> getBookList(){
return bookList;
}
}
如果要创建一个book实体类来保存读取到的XML文件内容,可以在endElement方法里判断标签内容,进而将characters方法里的valueset到book的相应属性中。这里也可以看出从节点头到节点内容再到节点尾,分别就对应着startElement,characters,endElement三个方法。
3. JDOM
- 仅使用具体类而不使用接口,灵活性低
- API大量使用了Collections类
先要导入JDOM的jar包
public class JDOMTest {
public static void main(String[] args) {
//创建一个SAXBuilder对象
SAXBuilder saxbuilder = new SAXBuilder();
try {
//将XML文件加载到输入流中,进而加载到SAXBuilder中
Document document = saxbuilder.build(new FileInputStream("books.xml"));
//获取XML文件的根节点
Element rootElement = document.getRootElement();
//获取根节点下的子节点的集合
List<Element> booklist= rootElement.getChildren();
for (Element book : booklist) {
//遍历每个book的属性
//若已经知道属性名,可通过book.getAttribute("id").getValue()获取
List<Attribute> bookAttrs = book.getAttributes();
for (Attribute attribute : bookAttrs) {
System.out.println(attribute.getName()+"--"+attribute.getValue());
}
//遍历每个book的子节点
List<Element> bookChildren = book.getChildren();
for (Element element : bookChildren) {
System.out.println(element.getName()+"--"+element.getValue());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
4. DOM4J
- JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能
- DOM4J使用接口和抽象基本类方法,是一个优秀的Java XML API
- 具有性能优异、灵活性好、功能强大和极端易使用的特点
先要导入DOM4J的jar包
public class DOM4JTest {
public static void main(String[] args) {
// 创建SAXReader的对象reader
SAXReader reader = new SAXReader();
try {
//加载books.xml文件
Document document = reader.read(new File("books.xml"));
//获取根节点
Element bookstore = document.getRootElement();
//获取迭代器
Iterator it = bookstore.elementIterator();
//迭代遍历
while(it.hasNext())
{
Element book = (Element) it.next();
//获取book的属性名以及属性值
List<Attribute> bookAttrs = book.attributes();
for (Attribute attr : bookAttrs) {
System.out.println(attr.getName()+"--"+attr.getValue());
}
//获取book的子节点及节点的值
Iterator it2 = book.elementIterator();
while(it2.hasNext())
{
Element bookChild = (Element) it2.next();
System.out.println(bookChild.getName()+"--"+bookChild.getStringValue());
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}