js使用dom解析标记型文档的方法:根据HTML的层级结构,在内存中分配一个树形结构,把HTML的标签、属性、文本都封装成对象。
对象类型:document对象、element对象、属性对象、文本对象、Node节点对象。
xml解析方式(技术):dom和sax
- dom:根据xml的层级结构,在内存中分配一个树形结构,把xml中的每部分都封装成对象。
优点:方便实现增删查改操作。
缺点:如果文件过大时,造成内存溢出。 - sax:采用事件驱动,边读边解析。
从上到下,一行一行解析对象,返回对象名称。
优点:不存在内存溢出,方便实现查询。
缺点:不能实现增、删、改操作。
解析xml的解析器
不同的公司和组织提供了针对dom和sax方式的解析器,通过API方式提供:
①sun公司提供了针对dom和sax的解析器 :jaxp
②dom4j组织:dom4j(实际开发中使用较多)
③jdom组织:jdom
jaxp的API查看
jaxp是javase的一部分。
jaxp解析器在jdk的javax.xml.parsers里面。共有四个类,分别是针对dom和sax解析使用的类:
- dom:
DocumentBuilder:解析器类
DocumentBuilderFactory:解析器工厂 - sax
SAXParser:解析器类
SAXParserFactory:解析器工厂
使用dom解析xml
DocumentBuilder是一个抽象类,不能new。可以从DocumentBuilderFactory.newDocumentBuilder()方法获取。
解析xml的方法:Parser " xml(路径) ",返回的是Document整个文档,返回的document是一个接口,父节点是Node。如果在document中找不到想要的方法,可以到父节点Node里去找。
解析步骤:
1.创建解析器工厂
2.根据解析工厂创建解析器
3.解析xml,返回document
4.得到所有的name元素
5.返回集合、遍历集合,得到每一个name元素
在document里面常用的方法:
- getElementsByTagName(String tagName)
这个方法可以得到标签,返回NodeList - createElement(String tagName) 创建标签
- createTextNode(String data) 创建文本
- appendChild(Node newChild) 把文本添加到标签上
- removeChild(Node oldChild) 删除节点
- getParentNode() 获取父节点
- getTextContent() 得到标签里的内容
NodeList list的方法:
- getLength() 得到集合长度
- item(int index) 取到下标的具体值
遍历NodeList:
for(int i=0;i<List.getLength();i++){
List.item(i);
}
使用jaxp实现查询
person.xml文件:
<?xml version="1.0" encoding="UTF-8">
<person>
<p1>
<name>张三</name>
<age>20</age>
</p1>
<p1>
<name>李四</name>
<age>21</age>
</p1>
</person>
查询所有name元素的值
Text.java文件:
public class Text {
public static void main(String [] args ) {
//创建解析器工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//创建解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//得到xml返回document
Document document=(Document) builder.parse("src/person.xml");
//得到name元素
NodeList list=((org.w3c.dom.Document) document).getElementsByTagName("name");
//遍历集合
for(int i=0;i<list.getLength();i++){
Node name1=(Node) list.item(i); //得到每一个name元素
String s=name1.getTextContent(); //得到每一个name元素的值
System.out.println(s);
}
}
}
查询xml中第一个name元素的值
将代码封装成一个方法:selectIn(),在main中调用。
步骤:
1.创建解析器工厂
2.根据解析器工厂创建解析器
3.解析xml,返回document
4.得到所有name元素
5.使用item方法通过下标获取第一个元素
6.得到具体的值,使用getTextContent()
public static void selectIn() throws Exception{
//创建解析器工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//创建解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//解析xml得到document
Document document builder.parse("src/person.xml");
//得到所有name元素
NodeList list = document.getElementsByTagName("name");
//使用下标得到第一个元素
Node name1= list.item(0);
//得到name的具体值
String si=name1.getTextContent();
}
使用jaxp添加节点
在person.xml文件中添加一个节点,在main中调用。
<p1>
<name>张三</name>
<age>20</age>
<sex>男</sex>
</p1>
步骤:
1.创建解析器工厂
2.根据解析器工厂创建解析器
3.解析xml,返回document
4.得到第一个p1,使用item下标获得
5.创建sex标签,createElement
6.创建文本,createTextNode
7.把文本添加到sex下面,appenChild
8.把sex添加到第一个p1下面
9.回写xml,前面的操作都是在xml内存中进行
Text.java文件:
private static void addSex() throws Exception{
//创建解析器工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//根据解析器工厂创建解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//解析xml
Document document=builder.parse("src/person.xml");
//得到第一个p1标签
NodeList list=document.getElementsByTagName("p1"); //得到所有p1
Node p1=list.item(0);
//创建sex标签
Element sex1=document.createElement("sex");
//创建文本
Element text1=document.createTextNode("男");
//把文本添加到sex下
sex1.appendChild(text1);
//把sex添加到p1
p1.appendChild(sex1);
//回写xml Transform(Source xmlSource,Result outputTarget)
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transform transform=transformerFactory.newTransformer();
transform.transform(new DOMSource(document), new StreamResult("src/person.xml"));
}
使用jaxp修改节点
修改第一个p1下面的sex为“女”,使用setTextContent()方法,在main中调用。
Text.java文件:
private static void modifySex() {
//创建解析器工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//根据解析器工厂创建解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//解析xml
Document document=(Document) builder.parse("src/person.xml");
Node sex1=document.getElementsByTagName("sex").item(0);
//修改sex值
sex1.setTextContent("女");
//回写xml
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transform transform=(Transform) transformerFactory.newTransformer();
transform.transform(new DOMSource((org.w3c.dom.Node) document), new StreamResult("src/person.xml"));
}
使用jaxp删除节点
删除第一个p1的sex节点,通过获取父节点getParentNode,删除removeChild()子节点。
private static void deleteSex() {
//创建解析器工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//根据解析器工厂创建解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//解析xml
Document document=(Document) builder.parse("src/person.xml");
Node sex1=document.getElementsByTagName("sex").item(0);
//得到sex的父节点
Node p1=sex1.getParentElement();
//删除操作
p1.removeChild(sex1);
//回写xml
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transform transform=(Transform) transformerFactory.newTransformer();
transform.transform(new DOMSource((org.w3c.dom.Node) document), new StreamResult("src/person.xml"));
}
使用jaxp遍历节点
遍历节点,把所有元素名称都打印出来。
使用递归算法实现:①得到根节点;②得到根节点的子节点;③得到根节点子节点的子节点…
private static void List() throws Exception{
//创建解析器工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//根据解析器工厂创建解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//解析xml
Document document=(Document) builder.parse("src/person.xml");
//编写一个方法实现遍历操作
List1();
}
private static void List1(Node node) {
//判断元素是否为元素类型时打印,无此判断时空格换行都打印
if(node.getNodeType()==Node.ELEMENT_NODE){
System.out.println(node.getNodeName());
}
//得到第一层子节点
NodeList list=node.getChildNodes();
//遍历list
for(int i=0;i<list.getLength();i++){
//得到每一个节点
Node node1=list.item(0);
List1(node1); //递归,自己遍历自己
}
}