java-XML
XML不再多说,XML 约束也不用说了,这里讲讲java如何对XML操作。
java中使用XML,目前常用的就是Jaxp(sun)和dom4j了,这里先讲讲java自带的Jaxp包
Jaxp的xml解析器有两种,一种是DOM解析器,一种是SAX解析器,两种各自应用在不同的场景上。
在DOM解析时,会把xml中各个节点视为对象,然后根据父子关系相互嵌套。优点时容易操纵,缺点也很明显,必须全部通读xml并加载进内存。
DOM解析的流程:
1,DocumentBuilderFactory是抽象类,newInstance()方法会根据本地平台安装的xml解析器自动创建相应的工厂实力
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
2,DocumentBuilder的newDocumentBuilder()方法会得到本地xml解析器相应的DocumentBuilder实力
DocumentBuilder documentB = dbf.newDocumentBuilder();
3,解析xml,根据DocumentBuilder的parse方法。
Document document = documentB.parse(new File(path));
//看文档可以知道,parse可以从解析File、InputSource(经过包装的InputStream)、InputStream和URI字符串
4,Document代表了整个XML文档,首先获取根节点,Element就是标签,它们都属于Node,也就是说,都实现了Node接口
Element root=document.getDocumentElement();
5,下面就是增删改查了
增加结点
//增加一个结点,注意,增加节点是对document操作,Document实现了这个方法 Element newStudent=document.createElement("student"); //增加一个属性,属性也算是结点,一切都是Node Attr cid=document.createAttribute("idcard"); //给属性设置值 cid.setValue("1121"); //将属性添加进这个标签 newStudent.setAttributeNode(cid); //最后,将这个结点添加进根节点,注意,是对根节点添加,不是Document root.appendChild(newStudent);
提取某节点信息(查)
//首先根据第3步,已经获得根结点,也就是Element root //获取所有标签名为sutdent的节点集合 NodeList students=root.getElementsByTagName("student"); //至于获取标签属性以及text内容,自行看手册 //要注意的是,换行和制表符'\n\t'这些,也会被当做text内容解析 //至于xml的编码问题,都是自动的,不用手动设置了。
更改结点内容(很多都是Node接口的方法,自行查看手册即可)
//设置标签内容 Node.setTextContent(String text) //设置属性内容 Attr.setValue(String value)
删除结点
Node.removeChild(Node node)
6,操作完xml,保存结果
//1、获得Transformer工厂 TransformerFactory tff=TransformerFactory.newInstance(); //2、对于DOM对象,使用树来表示,肯定是个多叉树了,,, //这个类,就是将树,变为结果树 Transformer tf = tff.newTransformer(); //3、把document(DOM)转换为xml source Source sc=new DOMSource(document); //4、创建一个DOM目标,这里是个流 Result rs=new StreamResult(new File(path_URI)); //5、将 XML Source 转换为 Result,这样就写入数据流了 tf.transform(sc, rs);
DOM解析就到这里,如果以网络流读取一个大的xml文件的话,这样肯定是不行的,不可能一直等到它全部读完载入内存再操作吧。。。。。光读取的话,就用SAX了。
事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理
我们常用的就是ContentHandler了。
下面是sax示例
//定义工厂api,用以配置和获取sax解析器 SAXParserFactory spf = SAXParserFactory.newInstance(); //得到解析器对象 SAXParser sp = spf.newSAXParser(); //得到一个xmlreader读取器 XMLReader xmlReader = sp.getXMLReader(); //注册一个内容事件处理器 ContentHandler,一般情况下,使用ContentHandler接口的已知 //子类DefaultHandler就行了 xmlReader.setContentHandler(new DefaultHandler(){ //为了方便,以内部类重写需要使用到的方法 //开始读取标签 public void startElement(String uri, //命名空间 String localName, //标签名 String qName, //限定名称 Attributes attributes //属性 ){ /////////////////////////// //获取标签的个数 attr.getLength(); //其它的看手册 } //开始读取文档 public void startDocument(){ } //读取到标签尾 public void endElement( String namespaceURI, String localName, String qName ) { } //读取标签体,注意的是,sax是分段读取的,每次最大读取是2kb public void characters(char[] ch, int start, int length ){ //读取大数据的时候注意sax是分段读取的,每次最大读取是2kb } }); //开始读取xml数据 xmlReader.parse("book.xml");
到这里,我们发现SAX虽然比DOM效率高,但是它是顺序读取的,无法回头,且只能从头到尾。
现在就可以使用Dom4j了,它是第三方包
//1.读取XML文件,获得document对象 SAXReader reader = new SAXReader(); Document document = reader.read(new File("input.xml")); //2.解析XML形式的文本,得到document对象. String text = "<members></members>";
Document document = DocumentHelper.parseText(text);
//3.主动创建document对象. Document document = DocumentHelper.createDocument(); //创建根节点 Element root = document.addElement("members");
dom4j 中结点对象的操作:
//1.获取文档的根节点. Element root = document.getRootElement(); //2.取得某个节点的子节点. Element element=node.element(“书名"); //3.取得节点的文字 String text=node.getText(); //4.取得某节点下所有名为“member”的子节点,并进行遍历. List nodes = rootElm.elements("member"); for (Iterator it = nodes.iterator(); it.hasNext();) { Element elm = (Element) it.next(); // do something } //5.对某节点下的所有子节点进行遍历. for(Iterator it=root.elementIterator();it.hasNext();){ Element element = (Element) it.next(); // do something } //6.在某节点下添加子节点. Element ageElm = newMemberElm.addElement("age"); //7.设置节点文字. element.setText("29"); //8.删除某节点. //childElm是待删除的节点,parentElm是其父节点 parentElm.remove(childElm); //9.添加一个CDATA节点. Element contentElm = infoElm.addElement("content"); contentElm.addCDATA(diary.getContent());
对节点对象属性的操作:
//1.取得某节点下的某属性 Element root=document.getRootElement(); //属性名name Attribute attribute=root.attribute("size"); //2.取得属性的文字 String text=attribute.getText(); //3.删除某属性 Attribute attribute=root.attribute("size"); root.remove(attribute); //4.遍历某节点的所有属性 Element root=document.getRootElement(); for(Iterator it=root.attributeIterator();it.hasNext();){ Attribute attribute = (Attribute) it.next(); String text=attribute.getText(); System.out.println(text); } //5.设置某节点的属性和文字. newMemberElm.addAttribute("name", "sitinspring"); //6.设置属性的文字 Attribute attribute=root.attribute("name"); attribute.setText("sitinspring");
在指定位置中插入元素:
//Element元素可以通过DocumentHelper对象得到。示例代码: Element aaa = DocumentHelper.createElement("aaa"); aaa.setText("aaa"); List list = root.element("书").elements(); list.add(1, aaa);
写入XML文档
//1.文档中全为英文,不设置编码,直接写入的形式. XMLWriter writer = new XMLWriter(new FileWriter("output.xml")); writer.write(document); writer.close(); //2.文档中含有中文,设置编码格式写入的形式.OutputFormat format = OutputFormat.createPrettyPrint();// 指定XML编码 format.setEncoding("GBK"); XMLWriter writer = new XMLWriter(newFileWriter("output.xml"),format); writer.write(document); writer.close();
XML与字符串的转换
//1.将字符串转化为XML String text = "<members> <member>sitinspring</member></members>"; Document document = DocumentHelper.parseText(text); //2.将文档或节点的XML转化为字符串. SAXReader reader = new SAXReader(); Document document = reader.read(new File("input.xml")); Element root=document.getRootElement(); String docXmlText=document.asXML(); String rootXmlText=root.asXML(); Element memberElm=root.element("member"); String memberXmlText=memberElm.asXML();
在Dom4j中使用xpath查询路径
xpath路径表达式就像正则表达式一样,可以免去自己写遍历对比代码了。
//dom4j的包中的document.......... List<Node> list = document.selectNodes("//xpath");
上面的所有代码基本上算是模板代码了,用的时候多看手册,拷贝粘贴就ok了