目录
xml解析
使用java代码。
js使用dom解析html:根据html的层级结构,在内存中分配一个树形结构,把html的标签,属性和文本都封装成对象:document、element、属性对象、文本对象、node节点对象。
xml的解析方式:dom和sax
- dom:根据xml的层级结构在内存中分配一个树形结构,方便实现增删改操作,但当文件过大会造成内存溢出。
- sax:采用时间驱动,边读边解析。从上到下,一行一行地解析,解析到某个对象,把对象名称返回。这种方式不会造成内存溢出、能方便地实现查询,但不能实现增删改操作。
- 想要解析xml,首先需要解析器。不同的公司和组织提供了针对dom和sax方式的解析器,通过api方式。
- sun公司:jaxp
- dom4j组织:dom4j(常用)
- jdom组织:jdom
jaxp的api的查看
jaxp是javase的一部分
jaxp解析器在jdk的javax.xml.parsers包里面。
四个类:分别是针对dom和sax解析使用的类。
dom
DocumentBuilder和DocumentBuilderFactory
- DocumentBuilder:解析器类
- 该类是一个抽象类,不能new对象。
- 此类的实例可以从DocumentBuilderFactory.newDocumentBuilder()方法获取
parse("xml路径")
可以解析xml,返回是Document整个文档
返回的document是一个接口,父接口是Node,如果在document里面找不到想要的方法,到Node里面去找。- document和Node里面的方法:getElementsByTagName、createElement、createTextNode、appendChild、removeChild、getParentNode
- NodeList集合的方法
getLength():得到集合长度(注意此处与javase不同,javase集合用size())
item(int index):返回集合中第index个项
//遍历集合
for(int i=0;i<list.length();i++){
list.item(i);
}
- DocumentBuilderFactory:解析器工厂
- 这个类也是一个抽象类。用newInstance()获取DocumentBuilderFactory的实例
使用jaxp查询节点
举例:查询所有name元素的值
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 用document的方法得到name集合
- 遍历集合得到元素和值 getTextContent()
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=bf.newDocumentBuilder();
Document d=db.parse("person.xml");
NodeList list=document.getElementsByTagName("name");
for(int i;i<list.length();i++){
Node name0=list.item(i);
//得到元素内容
String s=name0.getTextContent();
System.out.println(s);
}
使用jaxp添加节点
举例:在第一个name标签下添加<sex>nv</sex>
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 得到name集合,item(0)得到第一个name
- 创建标签、文本,并把文本添加到sex标签
- 把sex标签添加到第一个name
- 回写xml(解析后节点的改变仅在内存中,需要回写到xml文件)
public static void addSex() throws Exception
{
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance()
DocumentBuilder db=dbf.newDocumentBuilder=();
Document d=db.parse("person.xml");
NodeList list=d.getElementByTagName("name");
Node name1=list.item(0);
//-------------------
Element sex1=document.createElement("sex");
Text text=document.createTextNode("nv");
sex1.appendChild(text1);
name1.appendChild(sex1);
//-------------------
TransformerFactory tff=TransformerFactory.newInstance();
Transformer tf=TransformerFactory.newTransformer();
tf.transform(new DOMSouce(d),new StreamResult("person.xml"));
}
使用jaxp修改节点
举例:修改第一个sex的值
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 得到第一个sex元素
- 修改值 setTextContent
- 回写xml
public static void changeSex() throws Exception
{
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance()
DocumentBuilder db=dbf.newDocumentBuilder=();
Document d=db.parse("person.xml");
NodeList list=d.getElementByTagName("sex");
Node sex1=list.item(0);
//-------------------
sex1.setTextContent("nan");
//-------------------
TransformerFactory tff=TransformerFactory.newInstance();
Transformer tf=TransformerFactory.newTransformer();
tf.transform(new DOMSouce(d),new StreamResult("person.xml"));
}
使用jaxp删除节点
举例:删除第一个sex的值
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 获取sex元素
- 获取sex父节点
- 使用removeChild()删除
- 回写xml
public static void delSex() throws Exception
{
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance()
DocumentBuilder db=dbf.newDocumentBuilder=();
Document d=db.parse("person.xml");
NodeList list=d.getElementByTagName("sex");
Node sex1=list.item(0);
//--------------------
p1=sex1.getParentNode();
p1.removeChild(sex1);
//--------------------
TransformerFactory tff=TransformerFactory.newInstance();
Transformer tf=TransformerFactory.newTransformer();
tf.transform(new DOMSouce(d),new StreamResult("person.xml"));
使用jaxp遍历节点
打印xml中所有元素名称
- 创建解析器工厂
- 根据解析器工厂创建解析器
- 解析xml返回document
- 得到根节点
- 获取子节点(递归)
private static void listAll(Node node)
{
//判断是元素类型时才打印!!!!
if(node.getNodeType()==node.ELEMENT_NODE)
System.out.println(node.getNodeName());
//获取一层子节点
NodeList list=node.getChildNodes();
for(int i=0;i<list.getLength();i++)
{
Node node1=list.item(i);
listAll(node1);//递归
}
}
sax
SAXParser和SAXParserFactory
- SAXParser:是抽象类,实例通过SAXParserFactory.newSAXParser()获得
- parse(File f,DefaultHandler dh)
- 两个参数:xml路径、事件处理器
- parse(File f,DefaultHandler dh)
- SAXParserFactory:实例通过newInstance()得到
sax执行过程:
- 当解析到开始标签(
<root><head><title>
)的时候,自动执行startElement方法。其中的qname:返回名称 - 当解析到文本(
<body>
)时候,自动执行characters方法 - 当解析到结束标签(如
</head>
)时候,自动执行endElement方法
使用jaxp的sax方式解析xml
- 创建解析器工厂
- 创建解析器
- 执行parse方法
- 自己创建一个类,继承DefalultHandler
- 重写类里的三个方法:startElement、characters、endElement
public static void main(String[] args)throws Exception
{
SAXParserFactory spf=SAXParserFactory.newInstance();
SAXParser sp=spf.newSAXParser();
sp.parse("xml路径",new MyDefault())
}
class MyDefault extends DefaultHandler
{
此处右键>sourse>override选中三个方法导入
然后可以复写读取后的操作
}
使用jaxp的sax方式查询
此处有点迷…
举例:获取所有name元素的值
class MyDefault extends DefaultHandler
{
boolean flag=false;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if("name".equals(qName))
flag=true;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
//flag为真,说明解析到了name元素,可以打印
if(flag==true)
System.out.println(new String (ch,start,length));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
//name结束,将flag设为false
if("name".equals(qName))
flag=false;
}
}
sax获取第一个元素
例:获取第一个name元素的值
定义一个成员变量idx=1,结束方法的时候idx++
在characters方法里设置判断if(flag==true&&idx=1)