2 XML 以及XML解析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2 XML 以及XML解析相关的知识,希望对你有一定的参考价值。
一、XML1.XML:传输数据和保存数据
特点:有且只有一个根元素,xml结构为树形结构
2.XML文档结构分析(一切皆节点)
接口Node
子接口
Document :描述所有的xml文件
Element :描述所有的元素
Text :描述xml所有的文本内容(换行也是文本内容)
Attr :描述xml所有属性
3.xml的CDATA
用CDATA括起来的内容不会被xml文件解析,而是当成字符串使用。
<![CDATA[
中间的内容就是字符串<br>
]]>
二、XML解析
1.DOM解析(解析小型文件)
一次性将整个XML文件加载到内存中,形成一颗DOM树对象,操作xml,
实际上就是操作(增删改查)DOM对象即可, 操作完毕以后,要执行同步操作
①获取Document文档对象:
1.创建DocumentBuilderFactory对象
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
2.创建DocumentBuilder对象
DocumentBulider builder=factory.newDocumentBuilder();
3.创建Document对象
Document doc=builder.parse(f);
Document doc=builder.newDocument();
②常用API
Node接口:
getTextContent():获取文本内容
setTextContent():设置文本内容
appendChild(Node newChild):添加子元素
removeChild(Node oldChild):删除子元素
Document接口:
getDocumentElement():获取根元素
getElementsByTagName(""):根据指定的标签名获取所有子元素
createElement(""):创建元素
Element接口:(可以设置文本内容)
getElementByTagName(""):获取所有子元素
setAttribute("","");设置属性和属性值
getAttribute(""):获取属性值
③修改后,要执行同步操作:
同步操作核心类:Transformer
Transformer trans=TransformerFactory.newInstance().newTransformer();
执行同步方法:
trans.transform(Source xmlSource,Result outputTarget);
xmlSource使用DOMSource
outputTarget使用StreamResult
trans.transform(new DOMSource(doc),new StreamResult(new File(filePath)));
public void testGet() throws Exception {
// 步骤
// 1, 创建Document文档对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File(filePath));
// 2,获取根元素 <contacts>
Element root = doc.getDocumentElement();
System.out.println(root);
// 3,获取第二个联系人<linkman id="2">
NodeList linkmans = root.getElementsByTagName("linkman");
Element linkmanEL = (Element)linkmans.item(0);
// 4,获取第二个联系人的<name>元素
Node nameEL = linkmanEL.getElementsByTagName("name").item(0);
// 5, 获取<name>元素的文本内容
String name = nameEL.getTextContent();
System.out.println(name);
//6, 修改<name>的文本内容
nameEL.setTextContent("[email protected]");
//7, 创建联系人元素 <linkman>
Element linkmanEL = doc.createElement("linkman");
// 8,创建联系人的子元素 <name><email><address><group>
Element nameEL = doc.createElement("name");
Element emailEL = doc.createElement("email");
// 9, 设置子元素对应的文本内容
nameEL.setTextContent("虚竹");
emailEL.setTextContent("[email protected]");
// 10,将子元素添加到<linkman>
linkmanEL.appendChild(nameEL);
linkmanEL.appendChild(emailEL);
// 11,将<linkman>元素添加到根元素<contacts>中
root.appendChild(linkmanEL);
// 12, 同步操作
TransformerFactory factory = TransformerFactory.newInstance();
Transformer trans = factory.newTransformer();
//同步数据的数据来源
Source xmlSource = new DOMSource(doc);
//同步数据的目标
Result outputTarget = new StreamResult(new File(filePath));
trans.transform(xmlSource, outputTarget);
}
1.2 使用dom4j框架解析xml文件
//需求:获取第一个联系人的名称
@Test
public void testGetName() throws Exception {
//1,获取Document对象
SAXReader reader = new SAXReader();
String filePath = "C:/Users/YL/workspace/j1704/day05-xml-parse/contacts.xml";
Document doc = reader.read(new File(filePath));
//2. 获取根元素
Element root = doc.getRootElement();
//3,获取第一个联系人 <linkman id="1">
List linkmans = root.elements("linkman");
Element linkmanEL = (Element)linkmans.get(0);
//4,获取<name>元素
Element nameEL = linkmanEL.element("name");
String name = nameEL.getText();
String name = linkmanEL.elementText("name");
//5.获取第一联系人的id属性
Attribute attr = linkmanEL.attribute("id");
System.out.println(attr.getName()+" ---- "+attr.getValue());
System.out.println(name);
}
//添加一个 联系人
@Test
public void testAdd() throws Exception {
String filePath = "C:/Users/YL/workspace/j1704/day05-xml-parse/contacts.xml";
//1,获取Document文档和根元素
SAXReader reader = new SAXReader();
Document doc = reader.read(new File(filePath));
Element root = doc.getRootElement();
//2,创建一个linkman联系人
Element linkmanEL = root.addElement("linkman").addAttribute("id", "4");
//3. 创建linkman联系人的子元素
linkmanEL.addElement("name").addText("王姑娘");
linkmanEL.addElement("email").addText("[email protected]");
linkmanEL.addElement("addres").addText("河南");
linkmanEL.addElement("group").addText("少林");
//4. 同步操作(将修改的数据同步到磁盘)
//----------------普通的同步方法,同步到磁盘没有格式-------------------
// 1)创建FiewWrite对象
//FileWriter writer = new FileWriter(filePath);
//2) 创建 XMLWrite 对象,用于同步Document文档
//XMLWriter xmlWriter = new XMLWriter(writer);
//3)同步数据
//xmlWriter.write(doc);
//3)关闭流:一定要关闭
//xmlWriter.close();
//--------------漂亮的同步方法:有格式------------------
//1) 创建格式化对象
OutputFormat format = OutputFormat.createPrettyPrint();
//2)创建FiewWrite对象
FileWriter writer = new FileWriter(filePath);
//3)创建 XMLWrite 对象,用于同步Document文档
XMLWriter xmlWriter = new XMLWriter(System.out, format);
//4)同步数据
xmlWriter.write(doc);
//5)关闭流:一定要关闭
xmlWriter.close();
}
2.SAX解析
SAX(simple API for XML):是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析,但任何事物都有其相反的一面,对于SAX来说就是操作复杂。
SAX是事件驱动型XML解析的一个标准接口不会改变 SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
大多数SAX都会产生以下类型的事件:
1.在文档的开始和结束时触发文档处理事件。
2.在文档内每一XML元素接受解析的前后触发元素事件。
3.任何元数据通常由单独的事件处理
4.在处理文档的DTD或Schema时产生DTD或Schema事件。
5.产生错误事件用来通知主机应用程序解析错误。
需求:解析contacts.xml文件,将所有的linkman联系人封装到LinkMan对象中并且添加到list和中
SAX解析的核心类 : SAXParser
如何获取SAXParser 对象?
1, 创建 SAXParserFactory 对象
SAXParserFactory factory = SAXParserFactory.newInstance();
2, 创建 SAXParser对象
SAXParser parser = factory.newSAXParser();
3, 进行SAX解析
parser.parse(File f, DefaultHandler hb)
f : 需要解析 xml文件
hb : 解析器,真正干活解析的代码全在 DefaultHandler 中
public class SAXParseTest {
String filePath = "C:/Users/YL/workspace/j1704/day05-xml-parse/contacts.xml";
//需求:解析contacts.xml文件,将所有的linkman联系人封装到LinkMan对象中并且添加到list和中
@Test
public void testParse() throws Exception {
// 1, 创建 SAXParserFactory 对象
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2, 创建 SAXParser对象
SAXParser parser = factory.newSAXParser();
// 3, 进行SAX解析
//创建处理器对象
CustomeHanlder dh = new CustomeHanlder();
parser.parse(new File(filePath), dh);
//获取处理器解析的list集合
List<LinkMan> list = dh.getList();
for (LinkMan linkMan : list) {
System.out.println("解析结果:"+linkMan);
}
}
public class CustomeHanlder extends DefaultHandler {
// 创建list集合,存放联系人对象
@Getter
private List<LinkMan> list = new ArrayList<>();
//联系人对象
private LinkMan linkman;
//保存上一次元素名称
private String preTag;
// 元素开始时候调用
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 判断元素名称是linkman时创建对象
if ("linkman".equals(qName)) {
linkman = new LinkMan();
// 获取id属性
String id = attributes.getValue("id");
linkman.setId(Integer.valueOf(id));
}
//将qName 赋值给 成员变量 preTage ,在解析文本的时候就能获取上一次的元素名称
preTag = qName;
}
// 解析文本内容调用
public void characters(char[] ch, int start, int length) throws SAXException {
String value = new String(ch,start,length);
//排除所有为空的文本,换行等等
if(value!=null){
if("name".equals(preTag)){
linkman.setName(value);
}else if("email".equals(preTag)){
linkman.setEmail(value);
}else if("address".equals(preTag)){
linkman.setAddress(value);
}else if("group".equals(preTag)){
linkman.setGroup(value);
//此时linkman对象所有的数据都封装完毕可以添加list中去了
list.add(linkman);
}
}
}
// 元素结束时候调用
public void endElement(String uri, String localName, String qName) throws SAXException {
preTag = null;
}
// 文档开始时候调用
public void startDocument() throws SAXException {
}
// 文档结束时候调用
public void endDocument() throws SAXException {
}
}
以上是关于2 XML 以及XML解析的主要内容,如果未能解决你的问题,请参考以下文章