一.XML语法
- 在编写XML文档时,需要先使用文档声明来声明XML文档。且必须出现在文档的第一行。
最简单的语法:
<?xml version="1.0"?>
- 用encoding属性说明文档所使用的字符编码,默认为UTF-8。保存在磁盘上的文件编码要与声明的编码一致。
<?xml version="1.0" encoding="UTF-8"?>
- 用standalone属性说明文档是否独立,即是否依赖其他文档。
<?xml version="1.0" standalone="yes"?>
XML有两个编码: 要保证两个编码相同,都为UTF-8.
内容编码:
文件本身的编码:
XML编写语法:
- :xml有且仅有唯一的根标签
- :xml标签大小写敏感的
- :xml标签之间允许嵌套, 不允许交叉嵌套
CDATA是Character Data的缩写
作用:把标签当做普通文本内容;
<![CDATA[数据内容]]>
<?xml version="1.0" encoding="UTF-8"?>
<contacts>
<linkman id = "s1">
<name>Dusk</name>
<email>Dusk@163.com</email>
<address>中国广州</address>
<group>秘密机动组</group>
</linkman>
<linkman id = "s2">
<name>Gloam</name>
<email>Gloam@163.com</email>
<address>中国广西</address>
<group>秘密激动组</group>
</linkman>
</contacts>
二.获取Document对象
-
把一个XML文件加载进内存的时候,在内存中形成所谓的一种树状结构,我们把这一个结构称之为Document对象.
-
获取Document文档对象:
- :表示出需要被操作的XML文件的路径,注意是文件的路径,不是文件所在的目录.
``` File f = new File(“D:/contacts.xml”); ```
- :根据DocumentBuilderFactory类,来获取DocumentBuilderFactory对象.
注意:工厂设计模式往往体现着单例设计模式.
``` DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); ```
- :根据DocumentBuilderFactory对象,构建DocumentBuilder对象.
注意:XxxFactory,就是用来创建Xxx对象的.
``` DocumentBuilder builder = factory.newDocumentBuilder(); ```
- :根据DocumentBuidler对象,构建Document对象.
``` Document doc = builder.parse(f); ```
// 获取Document对象
@Test
public void testDOM() throws Exception {
// 获取DocumentBuilderFactory实例
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 根据工厂设计模式对象获取DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
// 根据DocumentBuilder对象获取Document对象
Document document = db.parse(file);
}
三.DOM解析常用API
1.node对象:
String getTextContent() : 获取当前元素的文本内容
void setTextContent(): 设置当前元素的文本的内容
Node appendChild(Node newChild): 给当前元素对象添加子元素对象
Node removeChild(Node oldChild): 删除指定的子元素
- document对象:
Element root = document.getDocumentElement(): 获取xml文件中的根元素
NodeList getElementsByTagName(String tagname): 获取xml文件中所有指定tagname的元素对象
Element getElementById(String elementId):
获取指定Id元素:
注意: 1:必须保证id唯一 2:必须给加上约束(dtd schema)
开发建议:不建议使用id来获取元素。 html 可以使用
Element createElement(String tagName): 创建一个指定名称的元素
- element对象:
NodeList nodeList = root.getElementsByTagName("linkman"): 获取当前元素指定标签名称子元素集合
void setAttribute(String name, String value): 给当前元素设置属性
- 同步转换:
TransformerFactory factory = TransformerFactory.newInstance();
//通过同步转换器工厂对象创建出同步转换器
Transformer transformer = factory.newTransformer();
//源:内存中document对象
Source xmlSource = new DOMSource(document);
//目标:磁盘文件
Result outputTarget = new StreamResult(f);
//同步转换
transformer.transform(xmlSource, outputTarget);
四.XML解析
// 获取文件
File file = new File("D:/java/TestFile/contacts.xml");
- 查询思路:
1:获取Document对象
2:获取根元素对象:contacts
3:获取根元素下找到第二个linkman元素
4:获取linkman元素下的第一个name元素
5:获取该name元素的文本内容
获取第一个联系人的姓名
// 获取第一个联系人的姓名
@Test
public void testQuery() throws Exception {
// 1)获取DocumentBuilder对象
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
// 2)获取Document对象
Document document = db.parse(file);
// 3)获取根元素
Element root = document.getDocumentElement();
// [contacts: null]
System.out.println(root);
// 4)根据根元素获取其子节点顺序元素集合
NodeList nodeList = root.getElementsByTagName("linkman");
System.out.println(nodeList.getLength());
// 5)获取root的第一个linkman
Element eleE1 = (Element) nodeList.item(0);
System.out.println(eleE1);
// 6)获取第一个linkma的第一个name的文本内容
String name = eleE1.getElementsByTagName("name").item(0).getTextContent();
System.out.println(name);
}
- 修改
思路:- :获取Document对象
- :获取根元素对象
- :获取第一个linkman元素
- :获取该linkman元素下的第一个email元素
- :修改email元素的文本内容
- :把内存中的数据同步到xml文件中(Transformer)
// 修改第二个联系人的email为ooxx@note.com
@Test
public void testChange() throws Exception {
// 1)获取Document对象
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
// 2)获取到第二个联系人的email节点
Element element = (Element) document.getDocumentElement().getElementsByTagName("linkman").item(1);
Element email = (Element) element.getElementsByTagName("email").item(0);
// 3)设置email为ooxx@note.com
email.setTextContent("ooxx@note.com");
// 4)同步转化
// 通过同步转化工程获取同步转化器
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
// 通过转化器的tansform(XmlSource,outputTarget)方法进行同步转化
Source xmlSource = new DOMSource(document);
Result outputTarget = new StreamResult(file);
transformer.transform(xmlSource, outputTarget);
}
- 增加
思路:- :获取Document对象
- :获取根元素
- :创建linkman,name,email,address,group元素
- :设置name,email,address,group元素的文本内容
- :设置name,email,address,group作为linkman的子元素
- :把新的linkman元素作为根的子元素
- :更新到xml文件中
// 新增一个联系人
@Test
public void testAdd() throws Exception {
// 1)获取Document实例
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
// 2)创建新联系人的节点
Element eleLinkman = document.createElement("linkman");
Element eleName = document.createElement("name");
Element eleEmail = document.createElement("email");
Element eleAddress = document.createElement("address");
Element eleGroup = document.createElement("group");
// 3)为新联系人的节点设置值
eleName.setTextContent("西门吹牛");
eleEmail.setTextContent("chuiniu@ximen.com");
eleAddress.setTextContent("太阳系地球");
eleGroup.setTextContent("风流人物");
// 4)把节点加入linkman中
eleLinkman.appendChild(eleName).appendChild(eleEmail).appendChild(eleAddress).appendChild(eleGroup);
// 5)把新建联系人linkman节点加入到根节点中
Element root = document.getDocumentElement();
root.appendChild(eleLinkman);
// 6)同步
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(file));
}
- 操作属性
思路:- 获取Document对象
- 获取根元素
- 获取第三个linkman元素
设置属性:需要同步
xx.xx()
获取属性:不需要同步
xx.xx()
// xml的属性操作第三个联系人属性操作
@Test
public void testAttribute() throws Exception {
// 1)获取第三个联系人的节点
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
Element eleLinkman = (Element) document.getDocumentElement().getElementsByTagName("linkman").item(2);
// 2)设置节点属性
eleLinkman.setAttribute("id", "s3");
// 修改
eleLinkman.setAttribute("id", "ss");
// 3)同步
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(file));
}
- 删除思路:
- :获取Document对象
- :获取根元素对象
- :获取第三个linkman元素
- :删除第三个linkman元素
- :更新到xml文件中
// 删除第三个联系人
@Test
public void testDelete() throws Exception {
// 1)获取Document对象
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
// 2)获取第三个联系人
Element eleLinkman = (Element) document.getDocumentElement().getElementsByTagName("linkman").item(2);
// 3)删除
eleLinkman.getParentNode().removeChild(eleLinkman);
// 4)同步
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(file));
}
五.案例
第一次保存一个联系人的时候,可能contacts.xml是不存在的,此时就得构建这一个文件.并把联系人信息存储到该文件中.
- 思路:
- :判断xml文件是否存在
- :不存在
- 创建document
- 创建根节点 contacts
- 将根节点添加到document中
- 进入第4步
- : 存在
- 获取Document
- 获取根节点 contacts
- 进入第4步
- :创建linkman,name,email,address,group元素
- :设置name,email,address,group元素的文本内容
- :设置name,email,address,group作为linkman的子元素
- :把新的linkman元素作为根的子元素
- :更新到xml文件中
// 判断是否存在xml文件如果不存在新建在新增联系人,如果存在,新增联系人
@Test
public void documentCase() throws Exception {
Document document = null;
DocumentBuilder db = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Element root = null;
// 1)判断是否存在该xml
if (!file.exists()) {
// 2)不存在新建Document对象,新建根节点加到Document对象中
document = db.newDocument();
root = document.createElement("contacts");
document.appendChild(root);
} else {
// 3)存在直接获取根节点
try {
document = db.parse(file);
root = document.getDocumentElement();
} catch (Exception e) {
// 当没有根节点的时候 新建Document对象,新建根节点加到Document对象中
document = db.newDocument();
root = document.createElement("contacts");
document.appendChild(root);
System.err.println("没有跟节点");
}
}
// 4)创建linkman,name,email,address,group节点
Element linkman = document.createElement("linkman");
Element name = document.createElement("name");
Element email = document.createElement("email");
Element address = document.createElement("address");
Element group = document.createElement("group");
// 5)为新建节点设置内容
name.setTextContent("西门吹火");
email.setTextContent("ximen@chuihuo.com");
address.setTextContent("中国钓鱼岛");
group.setTextContent("中国侠客");
// 6)把name,email,address,group节点加到linkman中 linkman加入到根节点中
linkman.appendChild(name);
linkman.appendChild(email);
linkman.appendChild(address);
linkman.appendChild(group);
root.appendChild(linkman);
// 7)同步
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(document), new StreamResult(file));
}