Dom(文档对象模型(Document Object Model))
W3C 文档对象模型 (DOM) 是中立于平台和语言的接口(可用于任何编程语言),它允许程序和脚本动态地访问和更新文档的内容、结构和样式。
Dom的特点:将文档一次性加入到内存,并解析为树状结构的数据。所以说Dom只适合于解析相对较小的文件,不然的话一次性读入到内存中,将很容易造成内存溢出。
整个文档是一个文档节点
每个 HTML 标签是一个元素节点
包含在 HTML 元素中的文本是文本节点
每一个 HTML 属性是一个属性节点
注释属于注释节点
——————————JAVA——————————
下面举个例子详细说明:用Dom4j解析people.xml文件
总结下,学习过程中遇到的小坑:
1.因为我创建的是一个maven项目,当时就是把people.xml放在代码文件一起,同一级目录下的,后来,始终都报null Nested exception,找不到对应的xml文件,才知道maven项目,非.java结尾的文件,放到src/main/java文件中都会找不着,必须对应的放到resource中去。
2.Collections.sort(people,(o1, o2) -> o1.getName().compareTo(o2.getName()));当name是中文字符的时候,这种方法的比较可能并不会得到我们想要的答案,我们需要利用Collactor来进行比较。如果需要使用特定地点的比较规则,则需要使用Collator.getInstance(Locale desiredLocale).
Collections.sort(people,(o1, o2) -> Collator.getInstance().compare(o1.getName(),o2.getName()));
先看一下people.xml文件:
第一步:生成saxreader对象,
SAXReader saxReader = new SAXReader();
第二步:生成document对象
Document document = saxReader.read(DomTest.class.getClassLoader().getResourceAsStream("com/bigdata/BBTree/people.xml"));
第三步:获取根节点
Element root = document.getRootElement();
第四步:获取根节点的子节点,返回值是一个list列表。
List<Element> el = root.elements();
对于Element,我们可以调用elements()方法,得到它的所有子节点。
一步步递归下去,就能得到所有的节点。
List<Element> el = root.elements();
for (Element e:el) { }
将每一步得到的结果进行输出,就可以得出树的大概结构。
那么我们通过遍历就能解析出每个节点的数据,从而进行对应的操作。
List<Person> people = new ArrayList<>();
Person p;
for (Element e:el) {
String name = e.element("name").getText();
int age = Integer.valueOf(e.elementText("age"));
String tel = e.elementText("tel");
p= new Person(name,age,tel);
people.add(p);
}
System.out.println(people);
——————————PYTHON——————————
对于python中使用dom4j,和java相比较就是换汤不换药。
首先需要的是,
1.手动导入模块:
from xml.dom.minidom import parse
2.运用导入的模块,生成document对象,此处people.xml跟python文件放用一级目录即可。
doc=parse("people.xml")
3.获取根节点:
e=doc.documentElement
4.根据tag获取各个节点信息,返回一个列表,可使用index访问具体某一个元素.
ps=e.getElementsByTagName("person")
nm=e.getElementsByTagName("name")[0]
这个时候就将xml中的数据解析出来了。不过通过对比,我感觉这棵树,和我们用java解析出来的那棵树还是不同的,具体我们来看下。
由图中运行结果可以看出,第一个Person元素的子节点就有7个,4个text node,3个element。这让我很是纳闷,捣鼓了好一会终于发现了,原来所谓的element元素就是写在尖括号中,也就是标签,而Text Node指的是写在外面的text,看下面这张图:
4个text node节点分别为元素节点和元素节点之间的回车换行和空格,
3个Element节点为name,age,tel三个元素。
而对于name节点而言,它的子节点就是一个Text node,zhangsan,这么一想,树的结构就清晰多啦。
下面就可以对解析出来的数据做处理啦:
people=[]
ps=e.getElementsByTagName("person")
for p in ps:
name=p.getElementsByTagName("name")[0].childNodes[0].data
age=p.getElementsByTagName("age")[0].childNodes[0].data
tel=p.getElementsByTagName("tel")[0].childNodes[0].data
p=Person(name,age,tel)
people.append(p)
print(people)
for p in sorted(people,key=lambda i:i.age ):
print(p)
people.sort(key=lambda p:p.name,reverse=True)
print(people)
总体来说还是比较简单,但是因为是一次性读取文件,所以在使用上只适用于小文件的解析,有一定的局限性,需要导入jar包才能使用。