例子
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="1">
<name>亨利谁与争锋</name>
<author>天下足球</author>
<year>2011</year>
<price>89</price>
</book>
<book id="2">
<name>贝影</name>
<year>2008</year>
<price>77</price>
<language>English</language>
</book>
</bookstore>
DOM解析、SAX解析、JDOM解析、DOM4J解析
DOM解析
(1)创建工厂、机器、对象
DocumentBuilderFactory dbf = new DocumentBuilderFactory();
DocumentBuilder db =dbf.DocumentBuilder();
Document document = db.parse("src/res/book.xml")
(2)解析节点属性名、节点属性值
①对于book节点个数未知
获取所有book节点的集合
Nodelist booklist = document.getElementByTagName("book");
使用for循环通过item()方法遍历每个book节点
Node book = booklist.item(i);
并获取book节点的所有属性集合
NameNodeMap attrs = book.getAttribute();
使用for循环通过item()方法遍历book的属性
Node attr = attrs.item(j);
获取属性名
attr.getNodeName();
获取属性值
attr.getNodeValue();
②对于已经找到book节点只有一个ID属性可用以下方法,使用强制类型转换
Element book = (Element) booklist.item(i);
String attrValue = book.getAttribute("id");
获取id属性的属性值:attrValue;
(3)解析子节点名、子节点值
Nodelist childNodes = book.getChildNodes();
遍历childNodes获取每个节点的节点名和节点值,其中节点中包括空格和换行符
使用for循环遍历
区分text类型和element类型的node,通过getNodeType();
childNodes.item(k).getNodeType() == Node.ELEMENT_NODE
childNodes.item(k).getNodeName();
获取子节点的节点值
需要先获取book子节点,然后获得子节点的子节点的节点值
chileNodes.ietm(k).getFirstChild().getNodeValue();
(4).getNodeValue()与.getTextContent()的区别
ChildNodes.item(i).getFirstChild().getNodeValue()与ChildNodes.item(i).getTextContent()的
区别:子节点中还包含其他子节点时,后者可以把子节点的值都显示出来。
getTextContent()获取节点中的text内容(即节点值).
getNodeType().............有text,element,attr三个
而Element如果要获取值,必须读取它的子节点,<name>content</name>认为content是namae的子节点;
两种方法:
getFirstChild().getNodeName();(获取子节点再获取值)
getTextContent();(获取content方法)
SAX解析
1.与DOM解析的差异
(1)在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,
从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致
内存溢出。
(2)SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。从xml文件
的最上面开始逐一解析每一个节点,可以对于每一个节点做出其处理方式。
SAXParser sp = spf.newSAXParser();
XMLReader xmlReader = sp.getXMLReader();
2.SAX解析XML文档
SAX解析XML文档的一般步骤:
(1)创建SAX解析工厂、解析器对象、XML的读取器
SAXParserFactory spf = SAXParserFactory.newInstance();SAXParser sp = spf.newSAXParser();
XMLReader xmlReader = sp.getXMLReader();
(2)设置读取器的事件处理器、解析xml文件
xmlReader.setContentHandler(new BookParserHandler());
xmlReader.parse("src/res/book.xml");
xmlReader.parse("src/res/book.xml");
(3)创建ParserHandler的类
并且重写startDocument、endDocument、startElement、endElement的方法
startDocument:解析xml文件的标签开始
endDocument:解析xml文件的标签开始
startElement:解析xml文件开始
endElement:解析xml文件开始
characters:解析xml节点属性
可以定义全局变量int bookindex = 0;为在main中设置解析每本书
(4)解析xml文件的节点属性
调用startElement(String url,String localName,String qName,Attributes attributes)方法;
开始解析book元素的属性
if(qName.equals("book")){
//已知book元素下属性名称,根据属性名称获取属性值
String value = attributes.getValue("id");
//不知道book元素下属性名和个数,可以使用for循环遍历book下属性
属性名:attributes.getQName(i);
属性值:attributes.getValue(i);
}
判断解析book是否结束
在endElement方法中使用
if(qName.equals("book")){
结束该本书的解析
}
(5)解析xml文件的节点名和节点间文本
解析文件的节点名,可以判断
if(!qName.equals("book")&&!qName.equals("bookstore")){
打印出}
解析节点值,
新建Characters方法
public void characters(char[] ch, int start, int length){
String value = new String(ch, start, length);
if(!value.trim().equals("")){//去掉文本后的空格
value;//可以得到节点值
}
}
(6)使用xml解析将xml的内容和结构存入Java对象
新建book类,创建所有属性,并创建get和set方法
并在解析book值时,将得到的属性值set进book的方法中。
JDOM解析
1.导入jar包
2.准备工作
(1)创建一个SAXBuilder对象
SAXBuilder saxBuilder = new SAXBuilder;
(2)创建一个输入流,将xml文件加载到输入流
InputStream in = new FileInputStream("src/res/books.xml");
(3)通过saxBuilder的build方法,将输入流加载到saxBuilder
Document document = saxBuilder.build(in);
(4)通过document对象获取xml的根节点
Element rootElement = document.getRootElement();
(5)获取根节点下的子节点的List集合
List<Element> bookList = rootElement.getChildren();
3.解析节点属性
(1)采用for循环遍历bookList中每个元素
for(Element book : bookList){
bookList.indexof(book);可以获取当前该本书处于bookList中的位置
}
(2)解析book的属性
List<Attribute> attrList = book.getAttributes();
遍历attrList(针对不清楚book节点下属性的名字及数量)
——————————————————————————————————————————————
book.getAttributeName("");
book.getAttributeValue("属性名");
用以上两种方法可以获取已知的节点属性名和属性值
——————————————————————————————————————————————
for(Attribute attr : attrList){
获取属性名
String attrName = attr.getName();
获取属性值
String attrValue = attr.getValue();
}
(3)解析子节点名和子节点值
List<Element> bookChilds = book.getChildren();
遍历bookChilds
for (Element child : bookChilds ){
child.getName();
child.getValue();
}
4.解析时乱码的处理
(1)encoding编解码方式更改
(2)若(1)无法解决时
在创建输入流时可以改为使用InputStreamReader( ,"UTF-8");
通过使用字符流的方式
5.JDOM中存储Book对象
(1)创建book对象
Book bookEntity = new Book();
(2)判断id属性
if(attrName.equals("id")){
bookEntity.setId(attrValue)
}
(3)判断属性名
if(child.getName().equals("name")){
bookEntity.setName(child.getValue());
}
通过以上方法对每一个属性都进行判断
(4)创建一个ArrayList来存储对象
private static ArrayList<book> booksList = new ArrayList<book>();
booksList.add(bookEntity);
bookEntity = null;
6.JDOM中jar包的引用
若按之前的操作,有可能会发生由于工程的导入导出操作导致jar丢失,此时可以按一下操作解决。
在package下new一个folder,然后将放在桌面的jar包复制进刚刚new的folder中去,然后在package中继续build path,然后选中刚刚复制的jar 包。
DOM4J解析
1.DOM4J解析节点
解析books.xml文件
(1)创建SAXReader的对象reader
SAXReader reader = new SAXReader();
(2)通过reader对象的read方法加载book.xml文件,获取document对象
Document document = reader.reader(new File("src/res/book.xml"));
(3)通过document对象获取根节点bookstores
Element bookStore = document.getRootElement();
(4)通过element独享的elementIterator方法获取迭代器
Iterator it = bookStore.elementIterator();
(5)遍历迭代器,获取根节点中的信息(书籍)
while(it.hasNext()){
Element book = (Element)it.next();
获取book的属性名和属性值
List<Attribute>bookAttrs = book.attribute();
遍历每本书中的所有节点
for (Attribute attr : bookAttrs){
获取属性名
attr.getName();
获取属性值
attr.getValue();
}
}
2.DOM4J解析子节点信息
遍历book子节点依然可以使用elementIterator方法获取迭代器
Iterator itt = book.elementIterator();
while(itt.hasNext()){
Element bookChild = (Element)itt.next();
获取节点名
bookChild.getName();
获取节点值
bookChild.getStringValue();
}
3.XPath
导包:javaxen.jar
Xpath是一个规范,
我们在使用基本用法的时候,都是基于查询的。
XPath的语法:
/开头,表示绝对路径
//开头:表示满足// 之后的所有元素
*:表示选择所有由 * 之前的路径所定位的元素 /*/*/*/BBB :表示在第三级目录下的BBB,不会找第四级目录下的BBB
/AAA/BBB[1]:表示选择此目录下的第一个BBB
/AAA[@id]:表示选择包含 id属性 的AAA
//找第一本书的作者
root.selectSingleNode("/书架/书/作者[1]");可能会变红,但是可以运行
实例:
<root> <success>1</success> <result> <item_0> <days>2018-05-19</days> <week>星期六</week> <citynm>北京</citynm> <temperature>28℃/16℃</temperature> <humidity>0%/0%</humidity> <weather>多云转阴</weather> <wind>西风</wind> <winp><3级</winp> <temp_high>28</temp_high> <temp_low>16</temp_low> <humi_high>0</humi_high> <humi_low>0</humi_low> </item_0> <item_1> <days>2018-05-20</days> <week>星期日</week> <citynm>北京</citynm> <temperature>21℃/16℃</temperature> <humidity>0%/0%</humidity> <weather>阴转小雨</weather> <wind>东风转东南风</wind> <winp><3级</winp> <temp_high>21</temp_high> <temp_low>16</temp_low> <humi_high>0</humi_high> <humi_low>0</humi_low> </item_1> </result> </root>创建一个天气类:weather
然后测试:
public class weatherTest { public static void main(String[] args) throws DocumentException { ArrayList<weather> weathers = new ArrayList<>(); //创建SAXReader的对象reader SAXReader reader = new SAXReader(); //通过reader对象的read方法加载book.xml文件,获取document对象 Document document = null; document = reader.read("weather.xml"); Element rootElement = document.getRootElement(); for (int i = 0; i <2 ; i++) { weather weather11 = new weather(); String item = "item_" + i; Element elem1 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/days"); weather11.setDate(elem1.getText()); Element elem2 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/week"); weather11.setWeek(elem2.getText()); Element elem3 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/citynm"); weather11.setCitynm(elem3.getText()); Element elem4 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/temperature"); weather11.setTemperature(elem4.getText()); Element elem5 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/weather"); weather11.setWeather(elem5.getText()); Element elem6 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/wind"); weather11.setWind(elem6.getText()); Element elem7 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/winp"); weather11.setWinp(elem7.getText()); Element elem8 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/temp_high"); weather11.setTemp_high(elem8.getText()); Element elem9 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/temp_low"); weather11.setTemp_low(elem9.getText()); Element elem10 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/humi_high"); weather11.setHumi_high(elem10.getText()); Element elem11 = (Element) rootElement.selectSingleNode("/root/result/" + item + "/humi_low"); weather11.setHumi_low(elem11.getText()); //添加到weathers中 weathers.add(weather11); } //输出weather for (weather wea : weathers) { System.out.println(wea); } } }
几种解析方法pk
1.分类
基础解析方式:DOM、SAX
扩展解析方式:JDOM、DOM4J
2.DOM解析过程:
一次性将整个xml文件加载到内存中,形成DOM树
优点:形成了树结构,直观好理解,代码更容易编写解析过程中树结构保留在内存中,方便修改
缺点:当xml文件较大时,对内存消耗比较大,容易影响解析性能并造成内存溢出
3.SAX解析过程:
逐条语句判断解析(基于时间的解析方式)
优点:采用事件驱动模式,对内存消耗比较小适用于只需要处理xml中数据时
缺点:不易编码,很难同时访问同一个xml中的多处不同数据
4.JDOM解析过程:
仅使用具体类而不使用接口
API大量使用了Collections类
5.DOM4J解析过程:
JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能
DOM4J使用接口和抽象基本类方法,一个优秀的Java XML API具有性能优异、灵活性好、功能强大和极端易使用的特点,
是一个开放源代码的软件