深入解读XML解析
一、XML是什么?有什么用?
XML是指可扩展标记语言(eXtensible MarkupLanguage),它是一种标记语言。它被设计的宗旨是描述数据(XML),而非显示数据(HTML)。
目前遵循的是W3C组织于2000年发布的XML1.0规范
应用场景:
1、描述数据
2、作为配置文件存在
二、XML的基本语法
1、文档声明:很重要
在编写XML文档时,需要先使用文档声明来声明XML文档。且必须出现在文档的第一行。
作用:告知解析器,我是一个XML文档。
最简单的声明语法:
<?xml version="1.0"?> 中间不要加空格,后面加?号
当我们写好的一个xml文件写入内存的时候会转换为二进制保存,这个时候会查码表,记事本保存的时候是gbk,而保存的时候默认查码表时用的是utf-8,
这个时候我们就可以用encoding属性:默认是UTF-8 <?xml version="1.0" encoding="GBK"?>,这样就可以解决乱码等问题。
standlone属性:该xml文件是否独立存在。
2、元素(标签)
XML语法非常严格。不能够省略结束标签。
一个XML文档必须有且仅有一个根标签
XML中不会忽略主体内容中出现的空格和换行
元素(标签)的名称可以包含字母、数字、减号、下划线和英文句点,但必须遵守下面的一些规范:
l 严格区分大小写;<P> <p>
l 只能以字母或下划线开头;abc _abc
l 不能以xml(或XML、Xml等)开头----W3C保留日后使用;
l 名称字符之间不能有空格或制表符;ab
l 名称字符之间不能使用冒号; (有特殊用途)
3、元素的属性
属性值一定要用引号(单引号或双引号)引起来
元素中属性不允许重复
4、注释
XML中的注释语法为:<!--这是注释-->
XML声明之前不能有注释 不允许第一行写注释(不同于java)
5、CDATA区
Character Data:字符数据。
语法:
<![CDATA[
内容
]]>
作用:
被CDATA包围的内容,都是普通的文本字符串。
6、特殊字符
特殊字符 替代符号
& &
< <
> >
" "
' &apos
7、处理指令(PI:ProcessingInstruction)(了解)
XML声明就是一种处理指令
处理指令:<?指令名称 属性?>
<?xml version="1.0" encoding="GBK"?>
<?xml-stylesheet type="text/css" href="main.css"?>
<world>
<chinese>中国</chinese>
<america>美国</america>
<japan>小日本</japan>
</world>
三、XML的约束
XML可以自定义。如果作为配置文件。
格式良好的XML文档:遵循XML语法的。
有效的XML文档:遵守约束的XML文档。
有效的XML文档必定是格式良好的,但良好的不一定是有效的。
1、DTD约束:(能看懂DTD即可)
a、DTD(Document Type Definition):文档类型定义
作用:约束XML的书写规范
注意:dtd可以写在单独的文件中,扩展名是dtd,且必须使用UTF-8编码进行保存。
b、XML文档中如何导入DTD约束文档(XML外部)
l dtd文档在本地:
<!DOCTYPE 根元素 SYSTEM "dtd文件的路径">
l dtd文档在网络上:
<!DOCTYPE 根元素 PUBLIC "dtd名称" "DTD文档的URL链接地址">
c、了解:也可以把DTD的内容直接写在XML文档内部。
写在XML文档内部,dtd没有编码要求。(了解)
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE 书架 [
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
<!ATTLIST 书
ISBN ID #REQUIRED
COMMENT CDATA #IMPLIED
出版社 CDATA "指令汇公司"
>
<!ENTITY copyright "指令汇公司">
]>
<书架>
<书 ISBN="a" COMMENT="ddd" 出版社="指令汇公司">
<书名>Java就业培训教程</书名>
<作者>©right;</作者>
<售价>39.00元</售价>
</书>
<书 ISBN="b">
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
</书架>
练习:
<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE TVSCHEDULE [
<!ELEMENT TVSCHEDULE (CHANNEL+)>
<!ELEMENT CHANNEL (BANNER,DAY+)>
<!ELEMENT BANNER (#PCDATA)>
<!ELEMENT DAY (DATE,(HOLIDAY|PROGRAMSLOT+)+)>
<!ELEMENT HOLIDAY (#PCDATA)>
<!ELEMENT DATE (#PCDATA)>
<!ELEMENT PROGRAMSLOT (TIME,TITLE,DESCRIPTION?)>
<!ELEMENT TIME (#PCDATA)>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT DESCRIPTION (#PCDATA)> <!ATTLIST TVSCHEDULE NAME CDATA #REQUIRED>
<!ATTLIST CHANNEL CHAN CDATA #REQUIRED>
<!ATTLIST PROGRAMSLOT VTR CDATA #IMPLIED>
<!ATTLIST TITLE RATING CDATA #IMPLIED>
<!ATTLIST TITLE LANGUAGE CDATA #IMPLIED>
]> <TVSCHEDULE NAME="NN">
<CHANNEL CHAN="CC">
<BANNER>AAA</BANNER>
<DAY>
<DATE>2015</DATE>
<PROGRAMSLOT>
<TIME>ee</TIME>
<TITLE>bb</TITLE>
<DESCRIPTION>cc</DESCRIPTION>
</PROGRAMSLOT>
</DAY>
</CHANNEL>
</TVSCHEDULE>
2、Schema约束(新,有替换DTD的趋势)
四、利用Java代码解析XML文档
1、解析方式
l DOM:Document Object Model,文档对象模型。这种方式是W3C推荐的处理XML的一种标准方式。
缺点:必须读取整个XML文档,才能构建DOM模型,如果XML文档过大,造成资源的浪费。
优点:适合对XML中的数据进行操作(CRUD)。
l SAX:Simple API for XML。这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它。
2、解析工具
JAXP:
DOM或SAX方式进行解析XML。API在JDK之中。
Dom4J:(推荐)
是开源组织推出的解析开发包。(牛,大家都在用,包括SUN公司的一些技术的实现都在用)
五、JAXP进行DOM方式解析XML基本练习
1、JAXP简介:
开发包:(JDK中)
DOM:W3C。org.w3c.dom.* DOM规范。(接口/抽象类)
SAX:开源组织。org.xml.sax.* SAX规范。(接口/抽象类)
JAXP:javax.xml.*
2、利用JAXP进行DOM方式解析
//JAXP进行DOM方式解析的基本操作
public class JaxpDemo1 { public static void main(String[] args) throws Exception {
//得到解析器
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//通过解析器就可以得到代表整个内存中XML的Document对象
Document document = builder.parse("src/book.xml");
test8(document);
}
// 1、得到某个具体的节点内容: 刘丰
private static void test1(Document document){
NodeList nl = document.getElementsByTagName("作者");
Node authorNode = nl.item(0);
System.out.println(authorNode.getTextContent());
}
// 2、遍历所有元素节点:打印元素的名称
private static void test2(Node node){
//确定node的类型
//方式一
// if(node.getNodeType()==Node.ELEMENT_NODE){
// //是元素
// }
//方式二
if(node instanceof Element){
//是元素
Element e = (Element)node;
System.out.println(e.getNodeName());//打印元素名称
}
//判断有没有子节点
NodeList nl = node.getChildNodes();
for(int i=0;i<nl.getLength();i++){
Node n = nl.item(i);
test2(n);
}
}
// 3、修改某个元素节点的主体内容:<售价>39.00元</售价>--->10元
private static void test3(Document document) throws Exception{
//得到售价
Node priceNode = document.getElementsByTagName("售价").item(0);
priceNode.setTextContent("10元");
//更新XML文件
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
//构建输入源:
Source source = new DOMSource(document);
//构建目标:
Result result = new StreamResult("src/book.xml"); t.transform(source, result);
} // 4、向指定元素节点中增加子元素节点:第一本书添加子元素 <出版社>黑马程序员</出版社>
private static void test4(Document document) throws Exception{
//创建:<出版社>黑马程序员</出版社>
Element e = document.createElement("出版社");
e.setTextContent("黑马程序员");
//得到书,把新节点挂上去
Node bookNode = document.getElementsByTagName("书").item(0);
bookNode.appendChild(e);
//更新XML文件
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
//构建输入源:
Source source = new DOMSource(document);
//构建目标:
Result result = new StreamResult("src/book.xml"); t.transform(source, result);
}
// 5、向指定元素节点上增加同级元素节点:第一本书<售价>前面添加<批发价>30</批发价>
private static void test5(Document document) throws Exception{
//创建新节点
Element e = document.createElement("批发价");
e.setTextContent("30元");
//找到<售价>
Node priceNode = document.getElementsByTagName("售价").item(0);
//父标签:调用insertBefore(新节点,参考节点); Node bookNode = priceNode.getParentNode();
bookNode.insertBefore(e, priceNode);
//更新XML文件
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
//构建输入源:
Source source = new DOMSource(document);
//构建目标:
Result result = new StreamResult("src/book.xml"); t.transform(source, result);
}
// 6、删除指定元素节点:删除批发价
private static void test6(Document document) throws Exception{
Node priceNode = document.getElementsByTagName("批发价").item(0);
priceNode.getParentNode().removeChild(priceNode);
//更新XML文件
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
//构建输入源:
Source source = new DOMSource(document);
//构建目标:
Result result = new StreamResult("src/book.xml"); t.transform(source, result);
}
// 7、操作XML文件属性:书籍添加一个属性:ISBN=“ABC”
private static void test7(Document document) throws Exception{
Node bookNode = document.getElementsByTagName("书").item(0);
if(bookNode instanceof Element){
Element e = (Element)bookNode;
e.setAttribute("ISBN", "ABC");
}
//更新XML文件
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t = tf.newTransformer();
//构建输入源:
Source source = new DOMSource(document);
//构建目标:
Result result = new StreamResult("src/book.xml"); t.transform(source, result);
}
// 8、操作XML文件属性:获取ISBN=“ABC”
private static void test8(Document document) throws Exception{
Node bookNode = document.getElementsByTagName("书").item(0);
if(bookNode instanceof Element){
Element e = (Element)bookNode;
System.out.println(e.getAttribute("ISBN"));
}
}
}
3、DOM小案例
a、建立xml文件
<?xml version="1.0" encoding="UTF-8" standalone="no"?><exam>
<student examid="222" idcard="111">
<name>刘丰</name>
<location>湖北</location>
<grade>100</grade>
</student>
<student examid="dsf" idcard="2342"><name>dsf</name><location>435</location><grade>654.0</grade></student></exam>
b、代码要精细。要分层。
DAO:com.zhilinghui.dao
VIEW:com.zhilinghui.view
JavaBean:com.zhilinghui.domain(领域)
c、设计JavaBean
public class Student {
private String idcard;
private String examid;
private String name;
private String location;
private float grade; public Student(){} public Student(String idcard, String examid, String name, String location,
float grade) {
super();
this.idcard = idcard;
this.examid = examid;
this.name = name;
this.location = location;
this.grade = grade;
}
public String getIdcard() {
return idcard;
}
public void setIdcard(String idcard) {
this.idcard = idcard;
}
public String getExamid() {
return examid;
}
public void setExamid(String examid) {
this.examid = examid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public float getGrade() {
return grade;
}
public void setGrade(float grade) {
this.grade = grade;
}
@Override
public String toString() {
return "Student [idcard=" + idcard + ", examid=" + examid + ", name="
+ name + ", location=" + location + ", grade=" + grade + "]";
} }
d、开发DAO
数据访问对象
public class StudentDao {
/**
* 保存学生信息到XML文件中
* @param student 封装要保存的信息
* @return 成功返回true,否则false
* @throws Exception
*/
public boolean save(Student student) throws Exception{ if(student==null)
throw new IllegalArgumentException("学生参数不能为null"); boolean result = false;
/*
* <student idcard="111" examid="222">
<name>刘丰</name>
<location>湖北</location>
<grade>100</grade>
</student>
*/ //得到Document
Document document = JaxpUtil.getDocument();
//创建一个student元素:设置属性
Element studentE = document.createElement("student");//<student></student>
studentE.setAttribute("idcard", student.getIdcard());
studentE.setAttribute("examid", student.getExamid());//<student idcard="111" examid="222"></student>
//创建name,location,grade元素,挂到student上
Element nameE = document.createElement("name");
nameE.setTextContent(student.getName());//<name>刘丰</name>
Element locationE = document.createElement("location");
locationE.setTextContent(student.getLocation());//<location>湖北</location>
Element gradeE = document.createElement("grade");
gradeE.setTextContent(student.getGrade()+"");//<grade>100</grade>
studentE.appendChild(nameE);
studentE.appendChild(locationE);
studentE.appendChild(gradeE);
//把student挂接到exam上
Node examNode = document.getElementsByTagName("exam").item(0);
examNode.appendChild(studentE);
//写到xml中
JaxpUtil.wirte2xml(document);
//更改result的取值为true
result = true; return result;
}
/**
* 根据姓名删除信息
* @param name
* @return 成功返回true,否则false
*/
public boolean delete(String name){
boolean result = false;
try {
Document document = JaxpUtil.getDocument();
//得到所有的name元素
NodeList nl = document.getElementsByTagName("name");
//遍历:比对文本内容是否和参数一样
for(int i=0;i<nl.getLength();i++){
if(nl.item(i).getTextContent().equals(name)){
//如果找到了一样的:爷爷干掉爸爸
nl.item(i).getParentNode().getParentNode().removeChild(nl.item(i).getParentNode());
//写回xml
JaxpUtil.wirte2xml(document);
break;
} }
result = true;
} catch (Exception e) {
throw new RuntimeException(e);//异常转译
}
return result;
}
/**
* 根据准考证号查询学生信息
* @param examid
* @return 没有返回null
*/
public Student findByExamId(String examid){
Student student = null;
try {
Document document = JaxpUtil.getDocument();
//得到所有的student元素
NodeList nl = document.getElementsByTagName("student");
//遍历:比对examid属性
for(int i=0;i<nl.getLength();i++){
Element e = (Element) nl.item(i);
if(e.getAttribute("examid").equals(examid)){
// 找到了:创建student对象,并设置相应的值
student = new Student();
student.setIdcard(e.getAttribute("idcard"));
student.setExamid(examid);
student.setName(e.getElementsByTagName("name").item(0).getTextContent());
student.setLocation(e.getElementsByTagName("location").item(0).getTextContent());
student.setGrade(Float.parseFloat(e.getElementsByTagName("grade").item(0).getTextContent()));
break;
}
}
} catch (Exception e) {
throw new RuntimeException(e);//异常转译
}
return student;
}
}
e、测试DAO的功能
public class StudentDaoTest { public static void main(String[] args) {
StudentDao dao = new StudentDao(); // Student student = new Student();
// student.setIdcard("333");
//
// dao.save(student); // Student s = dao.findByExamId("444");
// System.out.println(s); System.out.println(dao.delete("阿娇"));
} }
f、开发界面
ublic class Main { public static void main(String[] args) throws Exception {
StudentDao dao = new StudentDao(); System.out.println("a、添加用户\tb、查询成绩\tc、删除用户");
System.out.println("请输入操作类型:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String op = br.readLine();//读取用户输入的a|b|c
if("a".equals(op)){
//添加
System.out.println("请输入学生姓名:");
String name = br.readLine();
System.out.println("请输入学生准考证号:");
String examid = br.readLine();
System.out.println("请输入学生身份证号:");
String idcard = br.readLine();
System.out.println("请输入学生所在地:");
String location = br.readLine();
System.out.println("请输入学生成绩:");
String grade = br.readLine(); //封装数据
Student student = new Student(idcard, examid, name, location, Float.parseFloat(grade));
//调用dao
boolean b = dao.save(student);
if(b){
System.out.println("------添加成功------");
}else{
System.out.println("------服务器忙------");
}
}else if("b".equals(op)){
//查询
System.out.println("请输入学生准考证号:");
String examid = br.readLine();
Student s = dao.findByExamId(examid);
if(s==null)
System.out.println("------查无此人------");
else
System.out.println(s);
}else if("c".equals(op)){
//删除
System.out.println("请输入要删除的学生姓名:");
String name = br.readLine();
boolean b = dao.delete(name);
if(b){
System.out.println("------删除成功------");
}else{
System.out.println("------服务器忙------");
}
}else{
System.out.println("你傻呀,输错了");
}
} }
sax解析原理
在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。
SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器: 解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理
基本解析操作
//1解析器
SAXParser parse = SAXParserFactory.newInstance().newSAXParser();
//2获取xml读取器
XMLReader reader = parse.getXMLReader();
//3注册内容处理器
reader.setContentHandler(new ContentHandler1());
//4读取xml文档
reader.parse("src/book.xml");
封装读取书
封装到BOOK.java
public class sax3 {
//封装读取书
public static void main(String[] args) throws Exception {
SAXParser parse=SAXParserFactory.newInstance().newSAXParser();
XMLReader reader=parse.getXMLReader();
final List<Book> books=new ArrayList<Book>();
reader.setContentHandler(new DefaultHandler(){
private Book b=null;
private String currentTagName=null;
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
if("书".equals(qName)){
b=new Book();
}
currentTagName=qName;
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
if("书".equals(qName)){
books.add(b);
b=null;
}
currentTagName=null;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if("书名".equals(currentTagName)){
b.setName(new String(ch,start,length));
}
if("作者".equals(currentTagName)){
b.setAuthor(new String(ch,start,length));
}
if("售价".equals(currentTagName)){
b.setPrice(new String(ch,start,length));
}
}
});
reader.parse("src/book.xml");
for(Book book:books)
System.out.println(book);
}
}
dom4j解析原理
Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。 Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。 使用Dom4j开发,需下载dom4j相应的jar文件。
1、基本练习 a、拷贝jar包: 把dom4j-1.6.1.jar加入到你的classpath中 b、基本操作
// 1、得到某个具体的节点内容:金瓶梅
@Test
public void test1() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
//首先要得到根元素
Element root = document.getRootElement();
List<Element> bookElements = root.elements();
// Element bookName = (Element) bookElements.get(0).elements().get(0);
// System.out.println(bookName.getText());
System.out.println(bookElements.get(0).elementText("书名"));
}
// 2、遍历所有元素节点:名称
@Test
public void test2()throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
//首先要得到根元素
Element root = document.getRootElement();
treeWalk(root);
}
public void treeWalk(Element rootElement){//递归
System.out.println(rootElement.getName());
int nodeCount = rootElement.nodeCount();//子节点的数量
for(int i=0;i<nodeCount;i++){
Node node = rootElement.node(i);//得到一个子节点
if(node instanceof Element){
treeWalk((Element)node);
}
}
}
// 3、修改某个元素节点的主体内容:<售价>10元---20
@Test
public void test3()throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
//首先要得到根元素
Element root = document.getRootElement();
//得售价
Element priceElement = root.element("书").element("售价");
priceElement.setText("21元");
//写回XML文档
// OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
writer.write(document);
writer.close();
}
// 4、向指定元素节点中增加子元素节点:<出版社>黑马程序员
@Test
public void test4()throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
//首先要得到根元素
Element root = document.getRootElement();
//得售价
Element bookElement = root.element("书");
//创建新元素
Element publisherElement = DocumentHelper.createElement("出版社");
publisherElement.setText("黑马程序员");
bookElement.add(publisherElement);
//写回XML文档
// OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
writer.write(document);
writer.close();
}
// 5、向指定元素节点上增加同级元素节点:<售价>21元 添加<批发价>
@Test
public void test5()throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
//首先要得到根元素
Element root = document.getRootElement();
//得售价
Element bookElement = root.element("书");
//创建新元素
Element priceElement = DocumentHelper.createElement("批发价");
priceElement.setText("30元");
List<Element> bookChildren = bookElement.elements();//得到书的子元素
bookChildren.add(2, priceElement);
//写回XML文档
// OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
writer.write(document);
writer.close();
}
// 6、删除指定元素节点:批发价
@Test
public void test6()throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
//首先要得到根元素
Element root = document.getRootElement();
Element priceElement = root.element("书").element("批发价");
priceElement.getParent().remove(priceElement);
//写回XML文档
// OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
writer.write(document);
writer.close();
}
// 7、操作XML文件属性
@Test
public void test7()throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
//首先要得到根元素
Element root = document.getRootElement();
Element book = root.element("书");
System.out.println(book.attributeValue("ISBN"));
}
@Test
public void test8()throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
//首先要得到根元素
Element root = document.getRootElement();
Element book = root.element("书");
book.addAttribute("A", "B");
//写回XML文档
// OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
writer.write(document);
writer.close();
}
Xpath
XPath是一个努力为XSL转换XSLT和XPointer [ ] [ ]之间共享一个共同的XPointer功能语法和语义的结果。它的主要目的是解决一个XML XML文档部分[ ]。为了支持这一功能,还提供用于处理字符串的基本设施、数字和布尔值。XPath使用一个紧凑的、非XML语法方便使用在uri和XML属性值的XPath。XPath操作基于XML文档的逻辑结构,而不是其表面的语法。Xpath的名字来自其使用的符号在URL路径通过一个XML文档的层次结构导航。 除了用于定位,XPath还设计有一个真子集,可用于匹配(测试一个节点是否符合一个模式);使用XPath进行XSLT。
XPath模型的XML文档的节点树。有不同类型的节点,包括元素节点、属性节点和文本节点。XPath定义了一个方法来计算每个节点类型字符串值。某些类型的节点也有名字。XPath完全支持XML命名空间的XML名称] [。因此,一个节点的名称被建模为一个地方的部分和一个可能的空命名空间URI;这就是所谓的扩展名。在[ 5数据模型]中详细描述了数据模型。
@Test//Xpath
public void test11() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Node n = document.selectSingleNode("//书[1]/书名");
System.out.println(n.getText());
}
@Test//Xpath:第一本书的ISBN的值
public void test12() throws Exception{
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Node n = document.selectSingleNode("//书[1]");
System.out.println(n.valueOf("@ISBN"));
}
xml约束之schema
XML Schema 也是一种用于定义和描述 XML 文档结构与内容的模式语言,其出现是为了克服 DTD 的局限性
XML Schema 文件自身就是一个XML文件,但它的扩展名通常为.xsd。支持名称空间。 一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档。
和XML文件一样,一个XML Schema文档也必须有一个根结点,但这个根结点的名称为schema。
编写了一个XML Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URI地址上,在XML Schema技术中有一个专业术语来描述这个过程,即把XML Schema文档声明的元素绑定到一个名称空间上,以后XML文件就可以通过这个URI(即名称空间)来告诉解析引擎,xml文档中编写的元素来自哪里,被谁约束。
学习目标:不需要我们编写xsd 重点:根据xsd编写出xml文档。 难点:在xml中引入xsd约束
基本操作步骤:
a、根据xsd文件,找到根元素
<?xml version="1.0" encoding="UTF-8"?>
<书架>
</书架>
b、根元素来在哪个名称空间 使用xmlns关键字来声明名称空间。
<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com">
</tf:书架>
c、名称空间和哪个xsd文件对应
<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com"
schemaLocation="http://www.zhilinghui.com book.xsd">
</tf:书架>
d、schemaLocation来自一个标准的名称空间:固定写法
<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.zhilinghui.com book.xsd">
</tf:书架>
深入解读XML解析的更多相关文章
- PHP中的XML解析的5种方法
[前言]不管是桌面软件开发,还是WEB应用,XML无处不在!然而在平时的工作中,仅仅是使用一些已经封装好的类对XML对于处理,包括生成,解析等.假期有空,于是将PHP中的几种XML解析方法总结如下: ...
- XML概念定义以及如何定义xml文件编写约束条件java解析xml DTD XML Schema JAXP java xml解析 dom4j 解析 xpath dom sax
本文主要涉及:xml概念描述,xml的约束文件,dtd,xsd文件的定义使用,如何在xml中引用xsd文件,如何使用java解析xml,解析xml方式dom sax,dom4j解析xml文件 XML来 ...
- 【spring源码系列】之【xml解析】
1. 读源码的方法 java程序员都知道读源码的重要性,尤其是spring的源码,代码设计不仅优雅,而且功能越来越强大,几乎可以与很多开源框架整合,让应用更易于专注业务领域开发.但是能把spring的 ...
- xml解析技术
本文总结Dom,sax解析, 使用Java作为工具解析xml文档. 1 Dom 综述:Dom解析xml通常也称为xmlDom (和htmlDom技术差不多),将xml文档封装成树,好处就是xml中的 ...
- Duilib源码分析(三)XML解析器—CMarkup
上一节介绍了控件构造器CDialogBuilder,接下来将分析其XML解析器CMarkup: CMarkup:xml解析器,目前内置支持三种编码格式:UTF8.UNICODE.ASNI,默认为UTF ...
- JSON解析和XML解析对比
JSON解析和XML解析是较为普遍的两种解析方式,其中JSON解析的市场分额更大.本文系统的分析两种解析方式的区别,为更好地处理数据作准备.由于目前阶段主要是做移动开发,所以本文所描述的JSON解析和 ...
- 【Android】实现XML解析的几种技术
本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...
- 定位和xml解析和gson解析加上拉加载,下拉刷新
这里的上拉加载,下拉刷新用到是依赖包 Mainactivity,xml解析和定位 package com.exmple.autolayout; import java.util.List; impor ...
- tinyxml一个优秀的C++ XML解析器
读取和设置xml配置文件是最常用的操作,试用了几个C++的XML解析器,个人感觉TinyXML是使用起来最舒服的,因为它的API接口和Java的十分类似,面向对象性很好. TinyXML是一个开源的解 ...
随机推荐
- SpringBoot开发案例之多任务并行+线程池处理
前言 前几篇文章着重介绍了后端服务数据库和多线程并行处理优化,并示例了改造前后的伪代码逻辑.当然了,优化是无止境的,前人栽树后人乘凉.作为我们开发者来说,既然站在了巨人的肩膀上,就要写出更加优化的程序 ...
- ASP.NET CORE系列【六】Entity Framework Core 之数据库迁移
前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framework Core 发现园子里有些文章讲得不是那么细节,对于新手小白来说,可能会有点懵. 特意整理 ...
- LruCache的缓存策略
一.Android中的缓存策略 一般来说,缓存策略主要包含缓存的添加.获取和删除这三类操作.如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大 ...
- [PA 2014]Iloczyn
Description 斐波那契数列的定义为:k=0或1时,F[k]=k:k>1时,F[k]=F[k-1]+F[k-2].数列的开头几项为0,1,1,2,3,5,8,13,21,34,55,…你 ...
- [ZJOI2008]泡泡堂
题目描述 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组 ...
- 亲戚(relative)
[题目背景] Y 家是世界上最大的家族,HJZ 是其中一员. 现在 Y 家人想要拍一张全家福,却发现这是一个十分复杂的问题. . . . . . [题目描述] Y 家一共有 n 人 其中每个人最多有一 ...
- TopCoder SRM 559 Div 1 - Problem 900 CircusTents
传送门:https://284914869.github.io/AEoj/559.html 题目简述: n个实心圆,两两没有交集,在第一个圆上找一个点,使得它到另外一个圆上某个点的最短距离的最小值尽量 ...
- Go学习——new()和 make()的区别详解(转载)
这篇文章主要介绍了Go语言中new()和 make()的区别详解,本文讲解了new 的主要特性.make 的主要特性,并对它们的区别做了总结,需要的朋友可以参考下 概述 Go 语言中的 new 和 m ...
- operator[] 和 insert
operator[] 和 insert: map的[]操作和其他容器和内置[]没有关系 如果我们通过[]向map中插入or更新值,需要考虑一些东西 1.键已经存在,那么直接进行修改即可 2.键不存在, ...
- ZOJ 3228 Searching the String(AC自动机)
Searching the String Time Limit: 7 Seconds Memory Limit: 129872 KB Little jay really hates to d ...