XML文件解析之DOM解析
XML文件是一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便。基本的解析方式包括DOM解析和SAX解析,具体来说包括DOM解析,SAX解析,DOM4J解析以及JDOM解析,首先来讲下DOM解析的具体实现方式:
1.重要的对象
DocumentBuilderFactory: 创建文档解析器的工厂对象
DocumentBuilder :得到文档解析器对象,由工长对象获取
Document :文档对象
2.解析XML实现方式
XML文件:
<?xml version="1.0" encoding="UTF-8"?> <world> <comuntry id="1"> <name>China</name> <capital>Beijing</capital> <population>1234</population> <area>960</area> </comuntry> <comuntry id="2"> <name id="">America</name> <capital>Washington</capital> <population>234</population> <area>900</area> </comuntry> <comuntry id="3"> <name >Japan</name> <capital>Tokyo</capital> <population>234</population> <area>60</area> </comuntry> <comuntry id="4"> <name >Russia</name> <capital>Moscow</capital> <population>34</population> <area>1960</area> </comuntry> </world>
3.解析XML实现方式
1.获得DocumentBuilderFactory
2.获得DocumentBuilder
3.读取文件的输入流
4.获得文档的根元素调用递归函数进行处理
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class DOMParse { /** * 1.获得DocumentBuilderFactory * 2.获得DocumentBuilder * 3.读取文件的输入流 * 4.获得文档的根元素调用递归函数进行处理 * @param args */ public static void main(String[] args) { //获得DocumentBuilderFactory DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { //获得DocumentBuilder DocumentBuilder documentBuilder = factory.newDocumentBuilder(); //读取文件的输入流 InputStream inputStream = new FileInputStream(new File("world.xml")); //获得文档对象 Document document = documentBuilder.parse(inputStream); //获得文档的根元素 Element rootElement = document.getDocumentElement(); listChildNodes(rootElement,0); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 递归遍历并打印所有的ElementNode(包括节点的属性) * 1.首先处理该节点信息 * 2.处理节点的属性信息 * 3.处理子节点(递归方法实现) * @param node 表示节点对象 * @param level 节点所处的层次(从第一层根节点开始1) */ public static void listChildNodes(Node node, int level) { //只处理ElementNode类型的节点 if(level==0){ System.out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?> "); } if (node.getNodeType() == Node.ELEMENT_NODE) { boolean hasTextChild = false; String levelSpace = ""; for (int i = 0; i < level; i++) { levelSpace += " "; } //先打印ElementNode的开始标签 System.out.print(levelSpace + "<" + node.getNodeName() + (node.hasAttributes() ? " " : ">"));// 有属性的话节点的开始标签后面的尖括号">"就留待属性打印完再打印 if (node.hasAttributes()) {// 遍历打印节点的所有属性 NamedNodeMap namedNodeMap = node.getAttributes(); for (int i = 0; i < namedNodeMap.getLength(); i++) { System.out.print(namedNodeMap.item(i).getNodeName() + "=\""// 字符串里含双引号要用到转义字符\ + namedNodeMap.item(i).getNodeValue() + "\"" + (i == (namedNodeMap.getLength() - 1) ? "" : " "));// 不是最后一个属性的话属性之间要留空隙 } System.out.print(">");// 开始标签里的属性全部打印完加上尖括号">" } // 该ElementNode包含子节点时候的处理 if (node.hasChildNodes()) { level++;// 有下一级子节点,层次加1,新的层次表示的是这个子节点的层次(递归调用时传给了它) // 获得所有的子节点列表 NodeList nodelist = node.getChildNodes(); // 循环遍历取到所有的子节点 for (int i = 0; i < nodelist.getLength(); i++) { //子节点为TextNode类型,并且包含的文本内容有效 if (nodelist.item(i).getNodeType() == Node.TEXT_NODE && (!nodelist.item(i).getTextContent().matches("\\s+"))) {// 用正则选取内容包含非空格的有效字符的文本节点 hasTextChild = true;// 该ElementNode的一级子节点是存在有效字符的文本节点 System.out.print(nodelist.item(i).getTextContent());// 在开始标签后面添加文本内容 //子节点是正常的ElementNode的处理 } else if (nodelist.item(i).getNodeType() == Node.ELEMENT_NODE) { System.out.println(); // 递归调用方法 - 以遍历该节点下面所有的子节点 listChildNodes(nodelist.item(i), level);// level表示该节点处于第几个层次(相应空格) } } level--;// 遍历完所有的子节点,层次变量随子节点的层数,依次递减,回归到该节点本身的层次 // level++ 和 level--对于该节点的子节点影响的是子节点的初值 } //打印元素的结束标签.如果它的第一个一级子节点是有效文本的话,文本和结束标签添加到开始标签后面, //层次什么的就作废用不上了,否则,才按层次打印结束标签. System.out.print(((hasTextChild) ? "" : "\n" + levelSpace) + "</"+ node.getNodeName() + ">"); } } }
4.大功告成,这就是通过DOM方式实现了XML文件的解析,需要注意的地方就是那个递归调用函数,这个事实现动态解析的关键。用过知道了XML文件的内容,可以讲解析出来的具体对象封装起来,以便入库或者其他用处。有机会好好分享下。