java处理解析xml文件的几种方法及每种方法的区别
文章目录
- 了解xml
- xml文件的结构
- **特殊处理**
- **CDATA**
- 强烈建议
- 处理xml文件的几种方式
- 认识Document对象
- 解析xml文档
- 该选择哪种方式解析
- DOM解析xml文件
- DOM4j解析xml文档
- SAX方式解析xml
了解xml
xml全称(Extensible Markup Language)可扩展标记语言。
xml和HTML属于同宗同源,都是SGML的衍生语言,下面是两者之间的区别:
- xml是大小写敏感的,例如
<H1>
h和<h1>
是不同的xml标签; - 在xml中,属性值必须用引号括起来,在HTML中,引号是可有可无的,例如,
<applet code="MyApplet.class" width=300>
对于HTML来说是合法的,在xml中,必须使用引号,比如<applet width="300">
- xml中,属性名必须有值,HTML中可以没有值,例如
<applet code="MyApplet.class" width>
对HTML是合理的,但是对xml来时就是错误的,width属性必须有值,<applet code="MyApplet.class" width=“300”>
xml需要注意的是注释中不能有–,否则会报错,如<!--这是错误--的注释-->
错误后面的–是不能加的。
xml文件的结构
1、文件头
ML文件头由XML声明与DTD文件类型声明组成。其中DTD文件类型声明是可以缺少的,XML声明:
<?xml version="1.0" encoding="gb2312"?>
XML声明必须出现在文档的第一行。
2、文件体
有元素和元素属性组成,
3、约束文档
详解参考: https://blog.csdn.net/weixin_43790613/article/details/112425316
这个可有可无,可以提供一个文档类型定义(DTD)或一个XML Schema定义。作用是包含了用于解释文档应如何构成的规则,这些规则指定了每个元素的合法子元素和属性。不能添加指定外的元素和属性。
4. 命名空间
:详解参考: https://blog.csdn.net/weixin_43790613/article/details/112451194
特殊处理
实体引用
实体引用是指分析文档时会被字符数据取代的元素,实体引用用于XML文档中的特殊字符,否则这些字符会被解释为元素的组成部分。例如,如果要显示“<”,需要使用实体引用“<”否则会被解释为一个标记的起始。
CDATA
在XML中由一个特殊的标记CDATA,在CDATA中所有文本都不会被XML处理器解释,直接显示在浏览器中,使用方法如下:
<![CDATA[ 这里的内容可以直接显示。 ]]>
强烈建议
对于属性,一个常用的经验法则是,属性只应用来节点值得解释,而不是用来指定值,如正确的用法是
<font name="姓名" age="年龄"><name>张三</name><age>18</age>
</font>
错误的用法:
<font name="张三" age="18">
</font>
处理xml文件的几种方式
有DOM,SAX,JDOM和DOM4J
等;DOM和SAX是解析方式,JDOM和DOM4J是解析开发包;jsoup也是xml解析开发包,但解析HTML更加方便
认识Document对象
Document对象时xml文档的树形结构在内存中的表现,它由实现了Node接口及其子接口的对象构成
各个子接口的层次结构
解析xml文档
要处理xml文档,就要先解析它。解析器是这样一个程序:它读入一个文件,确认这个文件具有正确的格式,然后将其分解成各种元素,是的程序员能够访问这些元素。java库提供了两种xml解析器:
- 文档对象模型(Document Object Model,DOM)解析器这样的树形解析器,它们将读入的xml整个文档转换成树结构。
- XML简单API(Simple API for XML,SAX)解析器这样的流机制解析器,它们在读入xml文档时生成相应的事件。
该选择哪种方式解析
DOM解析器对于实现我们大多数目的来说更容易些,缺点是它需要读取整个文档到内存,需要消耗较多内存,如果文档过大,那就建议使用SAX方式读取文件
DOM解析xml文件
JDK中包含DOM解析器,所以不需要额外的jar包或依赖。
要读入一个XML文档,首先需要一个DocumentBuilder对象,可以从DocumentBuilderFactory中获取
解析前xml文档
<?xml version="1.0" encoding="gb2312"?>
<grandfather><import location="http://localhost:8000/user?wsdl=IUserService.wsdl" namespace="http://webservice.com/"></import><parent><son></son></parent><son></son>
</grandfather>
解析代码
try{DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();InputStream resourceAsStream = App.class.getClassLoader().getResourceAsStream("test1.xml");Document document = builder.parse(resourceAsStream);// getDocumentElement将返回根元素Element documentElement = document.getDocumentElement();// 通过节点名称获取所有此节点名称的节点NodeList sonNodeList = documentElement.getElementsByTagName("son");// 构建子节点,此节点可以添加到任意节点下Element name = document.createElement("name");name.setTextContent("姓名");for (int i = 0; i < sonNodeList.getLength(); i++) {// 获取指定索引的节点Node item = sonNodeList.item(i);// 可以用此判断只获取子节点if (item instanceof Element){Element element = (Element) item;System.out.println(element.getTextContent());// 添加子节点的方法element.appendChild(name);System.out.println(i);}}// 获取节点中的文本内容,一般要用trim方法,否则会有换行符String textContent = documentElement.getTextContent().trim();// 获取指定属性的值String location = documentElement.getAttribute("location");documentElement.setAttribute("test","测试属性");// 返回子节点的集合,此方法如果xml文件中没有DTD文件,则返回的除了子节点外还有节点之间的空格信息NodeList childNodes = documentElement.getChildNodes();//将构建好的xml输出到指定文件TransformerFactory transformerFactory = TransformerFactory.newInstance();Transformer transformer = transformerFactory.newTransformer();;
// 输出内容是否使用换行transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// 输出到文件//transformer.transform(new DOMSource(document), new StreamResult(new File("language.xml")));File file = new File("language.xml");
// file.createNewFile();FileWriter fileWriter = new FileWriter(file);// 之前用的file可以,但是后来就不行了,包文件名、目录名或卷标语法不正确。,改成filewrite就可以了transformer.transform(new DOMSource(document), new StreamResult(fileWriter));
}catch (Exception e){e.printStackTrace();
}
生成的文档
<?xml version="1.0" encoding="GB2312" standalone="no"?>
<grandfather test="测试属性"><import location="http://localhost:8000/user?wsdl=IUserService.wsdl" namespace="http://webservice.com/"></import><parent><son></son></parent><son><name>姓名</name>
</son>
</grandfather>
废了很大劲就是没有用代码将生成的xml文件格式化好,如有大佬知道,还望不吝赐教。还有就是name节点只在
DOM4j解析xml文档
需要用到的依赖
<dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version>
</dependency>
<!--使用xpath用到的依赖-->
<dependency><groupId>jaxen</groupId><artifactId>jaxen</artifactId><version>1.1-beta-8</version>
</dependency>
try {InputStream resourceAsStream = App.class.getClassLoader().getResourceAsStream("test1.xml");SAXReader saxReader = new SAXReader();Document document = saxReader.read(resourceAsStream);// 通过xpath获取节点Node node = document.selectSingleNode("/grandfather/parent/son");String sonNod = node.getText();System.out.println("zijiediandenrirong:" + sonNod);// 通过xpath获取节点并获取节点的属性
// document.// 获取根节点Element rootElement = document.getRootElement();// 获取属性值Attribute attribute = (Attribute)rootElement.selectSingleNode("/grandfather/import/@location");String value = attribute.getValue();System.out.println("属性值" + value);// 普通方法获取节点对象直接点element()方法即可,这种只能获取子节点Element sonElement = rootElement.element("子节点的节点名称");// 获取根节点下面的子节点Element anImport = rootElement.element("import");// 会获取匹配到的符合条件的节点就返回此节点,即哪个节点靠前就返回哪个节点Node sonN = rootElement.selectSingleNode("//son");// 表示不分任何层次结构的选择元素String sonNo = sonN.getText();System.out.println("22222222:" + sonNo);List<Node> sonNode = rootElement.selectNodes("//son");for (Node node1: sonNode) {String sonNod1 = node1.getText();System.out.println("111111111111:" + sonNod1);}// 添加节点和属性Node node1 = rootElement.addElement("person");node1.setText("新增加的节点");// 设置生成xml的格式,会有层次结构OutputFormat xmlFormat = OutputFormat.createPrettyPrint();// 没有层次结构,所有节点都在一行
// OutputFormat compactFormat = OutputFormat.createCompactFormat();//设置文件编码xmlFormat.setEncoding("UTF-8");// 设置换行
// xmlFormat.setNewlines(true);// 生成缩进
// xmlFormat.setIndent(true);// 使用4个空格进行缩进, 可以兼容文本编辑器xmlFormat.setIndent(" ");//创建写文件方法XMLWriter xmlWriter = new XMLWriter(new FileWriter("language.xml"),xmlFormat);//写入文件xmlWriter.write(document);//关闭xmlWriter.close();
} catch (Exception e) {e.printStackTrace();
}
SAX方式解析xml
此方式只适合获取节点信息,不适合修改xml文件
book实体类
package com.webservice;
/*** @author :li* @date :Created in 2020/12/12 21:34* @description:book实体类* @modified By:* @version: $*/
public class Book {private String title;private String author;private Double price;public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}@Overridepublic String toString() {return "Book{" +"title='" + title + '\'' +", author='" + author + '\'' +", price=" + price +'}';}
}
book.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<books><book><title>java基础</title><author>张三</author><price>45</price></book><book><title>C语言</title><author>李四</author><price>33</price></book>
</books>
MySaxHandler解析类
package com.webservice;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;import java.util.ArrayList;
import java.util.List;
/*** @author :li* @date :Created in 2020/12/12 21:24* @description:SAX解析器* @modified By:* @version: $*/
public class MySaxHandler extends DefaultHandler {private List<Book> list = new ArrayList<>();private String nodeName;private Book book;public List<Book> getList() {return list;}public void setList(List<Book> list) {this.list = list;}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {super.characters(ch, start, length);
// System.out.println("characters");String text = new String(ch, start, length);if ("title".equals(nodeName)){book.setTitle(text);}else if ("author".equals(nodeName)){book.setAuthor(text);}else if ("price".equals(nodeName)){book.setPrice(Double.parseDouble(text));}}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {super.endElement(uri, localName, qName);
// System.out.println("endElement");if (qName.equals("book")){list.add(book);}/*** 此处要设置为空,否则当节点为price时,会调用characters()方法,此时得到的文本内容会是空,而* 执行Double.parseDouble(text)回报错*/nodeName = "";}@Overridepublic void endDocument() throws SAXException {super.endDocument();
// System.out.println("endDocument");}@Overridepublic void startDocument() throws SAXException {super.startDocument();
// System.out.println("startDocument");}/**** @param uri 节点的命名空间 ,对命名空间的详细介绍https://www.runoob.com/xml/xml-namespaces.html* @param localName* @param qName 节点名称* @param attributes 属性实体类* @throws SAXException*/@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {super.startElement(uri, localName, qName, attributes);
// System.out.println("startElement");System.out.println("uri:" + uri + "===" + "localname:" + localName);this.nodeName = qName;Book book = null;if (qName.equals("book")){book = new Book();this.book = book;}}
}
测试类
package com.webservice;import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.util.List;
/*** @author :li* @date :Created in 2020/12/12 18:44* @description:通过SAX解析xml文档* @modified By:* @version: $*/
public class SAXTest {public static void main(String[] args) {SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();try {/*** 通过打印发现规律* 1、重写方法是按照startDocument、startElement、characters、endElement、endDocument执行的,* 且执行完所有节点的startElement后才开始执行endElement;* 2、每次执行startElement和endElement后就执行characters方法* 3、重写的方法的参数都是初始化好的*/InputStream resourceAsStream = SAXTest.class.getClassLoader().getResourceAsStream("book.xml");SAXParser saxParser = saxParserFactory.newSAXParser();MySaxHandler mySaxHandler = new MySaxHandler();saxParser.parse(resourceAsStream,mySaxHandler);// 获取解析到的数据List<Book> bookList = mySaxHandler.getList();for (Book book : bookList) {System.out.println("book====" + book );}} catch (ParserConfigurationException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}
}
java处理解析xml文件的几种方法及每种方法的区别相关推荐
- Java 实现解析xml文件的基本步骤(做笔记)
今天,初步学习了Java实现解析xml文件的基本步骤.不多说先上图解了. 源代码: public class Dome1 { public static void main(String[] args ...
- Java jdom解析xml文件带冒号的属性
Java jdom解析xml文件带冒号的属性 转载请标明出处: https://dujinyang.blog.csdn.net/article/details/99644824 本文出自:[奥特曼超人 ...
- Java - DOM4J解析XML文件
文章目录 1. XML文档说明 2. XML解析 2.1 常见的解析方式 2.2 DOM4J解析xml 2.3 XPath表达式解析XML 3. 解析XML并封装到类中 4. 参考资料 1. XML文 ...
- JAVA SAX解析XML文件
[代码] [Java]代码 view sourceprint? 001 package SAXparse; 002 003 004 import java.io.FileInputStream; 00 ...
- java jdom解析xml文件_Java 使用JDOM解析XML文档
使用JDOM解析XML文档 JDOM是一种使用 XML(标准通用标记语言下的一个子集) 的独特 Java 工具包.下面我们来看一下怎么使用 JDOM来解析XML文档. 首先下载JDOM的jar包,并导 ...
- Java中解析XML文件之SAX方式
1.SAX解析方式,是将XML文件逐行读进内存进行解析的. 2.首先编写一个SAXHandler(SAX处理类),这个类需要继承DefaultHandler类 3.在SAXHandler类中需要重写s ...
- java xsd 解析 xml文件_Java针对XSD文件验证XML文件的最佳方法是什么?
小编典典 Java运行时库支持验证.上次我检查的是幕后的Apache Xerces解析器.你可能应该使用javax.xml.validation.Validator. import javax.xml ...
- java xsd 解析 xml文件_xsd解析xml
下面讲述根据xml生成对应序列化反序列化类的过程,xml需要首先转化为xsd,然后再生成为实体类.其中,XSD是XML Schema Definition的缩写. 1.拥有一个xml文件 2.打开vs ...
- Java中DOM4J解析xml文件浅析
DOM4J解析它是JDOM的一种智能分支.它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持.XML Schema支持以及用于大文档或流化文档的基于事件的处理.它还提供了构建文档表 ...
最新文章
- HDU 3973 AC's String 字符串哈希
- Python基础——PyCharm版本——第四章、基础语法-分支语句(条件判断if语句)
- JavaScript的值传递和引用传递
- python if elif else_Python3使用独立的if语句与使用if-elif-else结构的不同之处
- 有关为旧版代码创建存根的更多信息–测试技术7
- fatfs文件系统f_lseek追加文件
- ggradar画雷达图
- Windows下部署ubuntu16.04+anaconda2.7+tensorflow
- Facade in Java
- 通过SecureCRT打开HCL模拟器命令行
- vue滚动条插件vue-happy-scroll
- 一文搞懂C语言如何用指针来代替变量和数组进行数据的存储
- 大数据知识梳理(Hadoop、HDFS)(整理中。。。)
- 元音上师海口开示观心
- iOS逆向小知识: Cycript Tricks Powerful private methods
- 评测三款免费的azw3阅读器(windows适用)
- 擎创动态 | 官宣!与深智城集团正式签约
- monodepth2 理解
- python将签名自动插入到PDF文件(PyPDF2)
- 计算机虚拟仪器技术文献,文献翻译-基于虚拟仪器技术的温度测控系统设计.doc...