5、XML解析
程序员文章站
2022-07-12 14:35:44
...
一、XML编程概述
- 一个XML文件除了我们人去读写以外,我们希望可以通过程序去读写,利用程序去增删改查XML的过程就是XML编程
- CRUD:Create、Read、Update、Delete
二、XML的两种解析方式
1、dom解析:
- 将整个XML使用类似树的结构保存在内存中,再对其进行操作。
- 是 W3C 组织推荐的处理 XML 的一种方式。
- 需要等到XML完全加载进内存才可以进行操作
- 耗费内存,当解析超大的XML时慎用。
- 可以方便的对xml进行增删改查操作
2、sax解析:
- 逐行扫描XML文档,当遇到标签时触发解析处理器,采用事件处理的方式解析xml
- (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。
- 在读取文档的同时即可对xml进行处理,不必等到文档加载结束,相对快捷
- 不需要加载进内存,因此不存在占用内存的问题,可以解析超大XML
- 只能用来读取XML中数据,无法进行增删改
3、图解
三、XML解析开发包
- Jaxp(sun,j2se)、dom4j(dom4j)
四、JAXP
- JAXP 开发包是J2SE的一部分,它由javax.xml、org.w3c.dom 、org.xml.sax 包及其子包组成
- javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 , DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法 ,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
- 使用JAXP进行DOM解析
-
调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂。 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); 调用工厂对象的 newDocumentBuilder方法得到 DOM 解析器对象。 DocumentBuilder builder = builderFactory.newDocumentBuilder(); 调用 DOM 解析器对象的 parse() 方法解析 XML 文档,得到代表整个文档的 Document 对象,进行可以利用DOM特性对整个XML文档进行操作了。 Document doc = builder.parse(new File("book.xml"));
- DOM编程
- DOM模型(document object model)
- DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点),并以树的结构组织起来,存储到内存中。
-
JAXP中的文档对象: Document:文档 Element:元素 Attr:属性 CharacterData:标签体 Node接口
- Node对象
- Node是一个接口,代表文档树中的单个节点,其他文档类都是Node接口的实现
- Node接口上提供了获取父节点、获取子节点的方法,由此可以遍历文档树。
- Node接口定义了增删改查节点方法由此可以修改文档树。
-
Node对象 Node getFirstChild() 此节点的第一个子节点。 Node getLastChild() 此节点的最后一个节点。 Node appendChild(Node newChild) 将节点 newChild 添加到此节点的子节点列表的末尾。 NodeList getChildNodes() 包含此节点的所有子节点的 NodeList。 getAttributes() 包含此节点的属性的 NamedNodeMap(如果它是 Element);否则为 null。 Node removeChild(Node oldChild) 从子节点列表中移除 oldChild 所指示的子节点,并将其返回。 Node replaceChild(Node newChild, Node oldChild) 将子节点列表中的子节点 oldChild 替换为 newChild,并返回 oldChild 节点。 void setTextContent(String textContent) 此属性返回此节点及其后代的文本内容。
- 更新XML文档
- 对文档树的增删该查只是对内存中的对象进行的操作,如果希望将修改对xml文件起作用,就需要进行XML文档更新
-
javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出 获取Transformer工厂 TransformerFactory transformerFactory = TransformerFactory.newInstance(); 获取Transfomer对象 Transformer transformer = transformerFactory.newTransformer(); 创建代表输入和输出的Source和Result对象 Source source = new DOMSource(doc); Result result = new StreamResult(new FIle("book.xml")); 使用Transformer将 XMLSource 转换为 Result transformer.transform(source , Result);
- SAX解析
- SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器。
- SAX解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定它去解析某个xml文档。
- SAX每当解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
- 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
-
- 阅读ContentHandler API文档,常用方法:startElement、endElement、characters
- SAX方式解析
-
使用SAXParserFactory创建SAX解析工厂 SAXParserFactory spf = SAXParserFactory.newInstance(); 通过SAX解析工厂得到解析器对象 SAXParser sp = spf.newSAXParser(); 通过解析器对象得到一个XML的读取器 XMLReader xmlReader = sp.getXMLReader(); 设置读取器的事件处理器 xmlReader.setContentHandler(new MyContentHandler()); 解析xml文件 xmlReader.parse("book.xml");
- AX方式解析--ContentHandler
-
void setContentHandler(ContentHandler handler) ContentHandler是一个接口,我们可以自己写一个类实现这个接口,其中提供了如下重要的方法: void characters(char[] ch, int start, int length) 接收字符数据的通知。 endDocument() 接收文档的结尾的通知。 startDocument() 接收文档的开始的通知。 startElement(String uri, String localName, String qName, Attributes atts) 接收元素开始的通知。 void endElement(String uri, String localName, String qName) 接收元素结束的通知。
- SAX方式解析DefaultHandler
- DefaultHandler是一个类,他默认实现了ContentHandler接口,并提供了其中所有方法的空实现,我们可以自己写一个类继承这个类,复写其中我们需要使用到的方法。
五、DOM4J解析XML文档
- Dom4j是一个简单、灵活的开放源代码的库。
- Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
- Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使 用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。
- 使用Dom4j开发,需下载dom4j相应的jar文件。
- DOM4J继承结构
-
Node |----Branch |----Document |----Element |----Attribute
- DOM4j解析xml文件
-
创建解析器: SAXReader reader = new SAXReader(); 利用解析器读入xml文档: Document document = reader.read(new File("input.xml")); 获取文档的根节点: Element root = document.getRootElement();
-
DOM4j节点 1.取得某个节点的子节点. Element element =ele.element(“书名"); List elementList =ele.elements(“书名"); List elementList =ele.elements(); 2.获取节点的名字 node.getName(); 3.设置节点的名字 node.setName(String newName); 4.取得节点的文字(标签体) String text=node.getText() 5.设置节点的文字(标签体) node.setText("aaa"); 6.添加子节点. ele.add(Element e);ele.addElement("age"); 7.删除子节点节点. parentElm.remove(childElm); 8获取节点类型 node.getNodeType() ; 9.获取父节点 node.getParent(); 10.取得某节点对象的某属性Attribute attr= ele.attribute("aaa"); Attribute attr= ele.attribute(0); List list = ele.attributes(); String value = ele.attributeValue("aaa"); Iterator it = ele.attributeIterator(); 11.设置某节点的属性 ele.add(Attribute attr); ele.addAttribute(name, value); ele.setAttributes(List attrs); 12.删除某属性 ele.remove(attribute); 13.在指定位置插入节点 1.得到插入位置的节点列表(list) 2.调用list.add(index,elemnent),由index决定element的插入位置。 Element元素可以通过DocumentHelper对象得到。示例代码: Element aaa = DocumentHelper.createElement("aaa"); aaa.setText("aaa"); List list = root.element("书").elements(); list.add(1, aaa);
-
DOM4j属性 1.取得属性的名、值 String name = attribute.getName(); String value = attribute.getValue(); 2.设置某属性的名、值 attribute.setName(); attribute.setValue();
- DOM4j字符串和XML的转换
-
1.将字符串转化为XML String text = "<members> <member>sitinspring</member</members>"; Document document = DocumentHelper.parseText(text); 2.将文档或节点的XML转化为字符串. String xmlStr = node.asXML();
- DOM4j将文档写入XML文件
- 方式一:
-
调用Node提供的write(Writer writer) 方法,使用默认方式将节点输出到流中: node.write(new FileWriter("book.xml"));
- 乱码问题:Dom4j在将文档载入内存时使用的是文档声明中encoding属性声明的编码集进行编码,如果在此时使用的writer的内部编码集与最初载入内存时使用的编码集不同则会出现乱码问题。
- FileWriter默认使用操作系统本地码表即gb2312编码,并且无法更改
- 此时可以使用OutputStreamWriter(FileOutputStream("filePath"),"utf-8");的方式自己封装一个指定码表的Writer使用,从而解决乱码问题
- 方式二:
利用XMLWriter写出Node: XMLWriter writer = new XMLWriter(new FileWriter("output.xml")); writer.write(node); writer.close();
- 注意:使用这种方式输出时,XMLWriter首先会将内存中的docuemnt翻译成UTF-8格式的document,在进行输出,这时有可能出现乱码问题
-
可以使用OutputFormat 指定XMLWriter转换的编码为其他编码。 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("GBK"); XMLWriter writer = new XMLWriter(newFileWriter("output.xml"),format);
- Writer使用的编码集与文档载入内存时使用的编码集不同导致乱码,使用字节流或自己封装指定编码的字符流即可。
-
DOM4j--DocumentHelper createDocument(); createDocument(Element rootEle createAttribute(Element owner, String name, String value)); createElement(String name); Docuemnt parseText(String text);
六、DOM4j--XPath
从根路径开始的绝对路径方式获取/AAA 例子:获取所有AAA下的BBB下的所有CCC:/AAA/BBB/CCC 所有指定名称的元素//AAA 例子:获取所有名称为AAA的元素 使用*号匹配福获得所有满足条件的元素 例子:获取AAA下BBB下所有的元素:/AAA/BBB/* 使用中括号,获取多个匹配元素中的某一个,可以使用last()函数获取最后一个 例子:获取AAA下所有BBB的第二个:/AAA/BBB[2] 例子:获取AAA下所有BBB的最后一个:/AAA/BBB[last()] 指定某一属性:@AttName,可以配合中括号使用 例子:获取所有id属性://@id 例子:获取所有具有id属性的BBB元素://BBB[@id] 例子:获取所有不具有属性的BBB元素://BBB[not(@*)] 例子:获取属性的值为某一个固定值的BBB元素://BBB[@id='b1'] //BB[@name='ddd' and @psw='dddf']
上一篇: 6、JavaWEB开发入门
下一篇: 4、XML约束--Schema约束