目前常用的XML解析技术有四种:DOM解析;SAX解析;JDOM;DOM4J
1. DOM解析
优点:适用于多次访问XML的应用程序;缺点:解析比较消耗资源
2. SAX解析
优点:资源占用少,内存消耗小
3. JDOM解析
优点:简化和XML之间的交互,使用速度快;缺点:限制了灵活性
4. DOM4J解析
优点:性能优异、功能强大、易用
本篇文章主要讲DOM解析,下篇文章讲解DOM4J解析的使用
一、DOM解析
目的一:将以下的XML文件通过解析用JAVA语言在控制台上输出
<?xml version="1.0" encoding="UTF-8"?> <books> <book> <title>三国演义</title> <author>罗贯中</author> <price>30元</price> </book> <book> <title>水浒传</title> <author>施耐庵</author> <price currencu="renminbi">35元</price> </book> </books>
先创建一个解析器工厂:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();//千万不能直接new
有了解析器工厂之后,生产出一个解析器:
DocumentBuilder db;//会报一个异常,捕捉一下 { try { db = factory.newDocumentBuilder();//也是不能直接new,要用解析器工厂去生产出来 } catch (ParserConfigurationException e) { e.printStackTrace(); } }
有了解析器,就可以生产出一个DOM树了:
//获得DOM树 Document document; { try { document = db.parse("E:\\IJ\\src\\XMLAdditional\\BookDOM.xml");//1、放文件2、也是不能直接new的哦 } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
用获得的DOM树.getElementsByTagName();可以根据元素名获得所需要的元素,返回的是一个指定元素名的节点的集合
NodeList bookList = document.getElementsByTagName("book");//得到book的集合,也就是《三国演义》、《水浒传》这两本书
通过遍历,得到元素集合中的一个
for (int i = 0; i < bookList.getLength(); i++) { Element bookElement = (Element) bookList.item(i);//得到其中一本,一本本的分析
String bookTitle = bookElement.getElementsByTagName("title").item(0).getFirstChild().getNodeValue(); String bookAuthor = bookElement.getElementsByTagName("author").item(0).getFirstChild().getNodeValue(); String bookPrice = bookElement.getElementsByTagName("price").item(0).getFirstChild().getNodeValue();
分析上述代码,以第一句为例。先通过getElementsByTagName()得到元素名称是title的集合,然后.iteam(),获得title集合的第0个位置(第0个位置是因为book标签下面的title集合中中title只有一个),是一个Element类型的,是单个元素,然后 .getFistChild()得到得到title下面的第一个子节点,最后通过 .getNodeValue()方法得到子节点的文本。通过这样的方法得到author和price。
根据XML中看,水浒传中的price有一个currencu的属性节点,三国演义这本书没有,所以还要通过判断将这个属性节点显示出来
先根据price集合中第0个位置的节点 .hasAttributes()判断是不是有属性;然后指定节点 .getAttribute()得到currencu的内容。
String currencuName=""; boolean currencuElement = bookElement.getElementsByTagName("price").item(0).hasAttributes(); if (currencuElement==true) { Element element= (Element) bookElement.getElementsByTagName("price").item(0); currencuName =element.getAttribute("currencu"); }
最后输出
System.out.println("书名:"+bookTitle+",作者"+bookAuthor+",价格"+bookPrice+currencuName);
到这里,就完成了输出XML中的显示文本信息的要求。
目的二:增加一个<book></book>,book中的内容为<title>西游记</title>;<author>吴承恩</author>;<price>40元</price>
<?xml version="1.0" encoding="UTF-8"?> <books> <book> <title>三国演义</title> <author>罗贯中</author> <price>30元</price> </book> <book> <title>水浒传</title> <author>施耐庵</author> <price currencu="renminbi">35元</price> </book> </books>
明确XML结构,books是根元素,也就是第一节点,book是第二节点,title,author,price是第三节点,西游记、吴承恩、40元是第四文本节点。
通过document.createElement创建节点,先创建所有需要添加的节点、(此时不需要设置节点的顺序关系,但是建议加注释或者按顺序写,便于理解)
//创建第二节结点 Element totalBook=document.createElement("book"); //创建第三节结点 Element bookTitle=document.createElement("title"); Element bookAuthor=document.createElement("author"); Element bookPrice=document.createElement("price"); //创建对应的文本节点 Text name=document.createTextNode("西游记"); Text author=document.createTextNode("吴承恩"); Text price=document.createTextNode("85");
创建完所有的节点之后,建立各个节点的层次关系,用Element的appendChild方法(建议按照顺序放,避免遗漏和混乱)
//文本节点到三节 bookTitle.appendChild(name); bookAuthor.appendChild(author); bookPrice.appendChild(price); //三节到二节 totalBook.appendChild(bookTitle); totalBook.appendChild(bookAuthor); totalBook.appendChild(bookPrice); //二节到跟元素 Element books= (Element) document.getElementsByTagName("books").item(0); books.appendChild(totalBook);
至此,增加完成,但是XML中还是原来的两本书,没有将西游记添加进去。
目的三:将增加在控制台的内容保存到XML中
和创建DOM解析器工厂相似,要保存就要先创建转换器工厂
//获得转换器工厂 TransformerFactory factory=TransformerFactory.newInstance();//不能new
获得工厂之后,可以设置缩进,确保保存到XML中的格式一致
//设置缩进 factory.setAttribute("indent-number",4);
获得转换器
//获得转换器 Transformer transformer=factory.newTransformer();//不能new
获得转换器之后可以设置属性(主要是允许缩进和编码格式)
//设置属性 transformer.setOutputProperty(OutputKeys.ENCODING,"UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT,"YES");
接下来就根据转换器 .transfom()进行转换,但是我们调方法的时候发现,这个时候需要传一个Source和Result类型的值进去。
获得Source类型的值:
DOMSource domSource=new DOMSource(document);
获得Sesult类型的值:
StreamResult result=new StreamResult(new OutputStreamWriter(new FileOutputStream("E:\\IJ\\src\\XMLAdditional\\BookDOM.xml"),"UTF-8"));
然后再进行转换
transformer.transform(domSource,result);