XML简介
-
XML基本概念
-
XML(eXtensible Markup Language)
-
可扩展标记语言:意义+数据
-
标签可自行定义,具有自我描述性
-
纯文本表示,跨系统/平台/语言
-
W3C标准
-
-
常规语法
-
任何的起始标签都必须有一个结束标签
-
简化写法,例如,
可以写成 -
大小写敏感
-
每个文件都要有一个根元素
-
标签必须按合适的顺序嵌套,不可错位
-
所有的特性都必要有值,且在值的周围加上引号
-
需要转义字符,如"<"需要用
<
代替<
< 小于 >
> 大于 &
& 和号 '
' 单引号 "
" 双引号 -
注释:
-
-
XML扩展
-
DTD(Document Type Definition)
- 定义XML文档的结构
- 使用一系列合法的元素来定义文档结构
- 可嵌套在xml文档中,或者在xml中引用
-
XML Shema(XSD,XML Schema Definition)
- 定义XML文档的结构,DTD的继任者
- 支持数据类型,可扩展,功能更完善、强大
- 采用xml编写
-
XSL
-
扩展样式表语言(eXtensible Stylesheet Language)
-
XSL作用于XML,等同于CSS作用于HTML
-
内容:
XSLT:转换XML文档
XPath:在XML文档中导航
XSL-FO:格式化XML文档
-
-
XML解析(DOM方法)
-
XML解析方法
-
树结构
- DOM:Document Object Model 文档对象模型,擅长(小规模)读/写
-
流结构
- SAX:Simple API for XML 流机制解释器(推模式),擅长读
- Stax:The Streaming API for XML 流机制解释器(拉模式),擅长读
-
-
DOM是W3C处理XML的标准API
处理方式是将XML整个作为类似树结构的方式读入内存中以便操作及解析,方便修改。
解析大数据量的XML文件,会遇到内存修理及程序崩溃的风险。
-
DOM类
- DocumentBulider解析类,parse方法
- Node节点主方法,getChildNodes返回一个NodeList
- NodeList节点列表,每个元素是一个Node
- Document文档根节点
- Element标签节点元素(每个标签都是标签节点)
- Text节点(包含在XML元素内的,都算Text节点)
- Attr节点(每个属性节点)
-
示例
public class DomReader { public static void main(String[] args) { recursiveTraverse(); System.out.println("======分割线======="); traverseBySearch(); } public static void recursiveTraverse() { try { // 采用DOM解析xml文件 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse("user.xml"); // 获取所有的一级节点 NodeList usersList = document.getChildNodes(); System.out.println("The 1st level length:"+usersList.getLength()); for(int i=0;i<usersList.getLength();i++) { Node users = usersList.item(i); NodeList userList = users.getChildNodes(); System.out.println("The 2nd level length:"+userList.getLength()); for(int j=0;j<userList.getLength();j++) { Node user = userList.item(j); if (user.getNodeType() == Node.ELEMENT_NODE) { NodeList metaList = user.getChildNodes(); System.out.println("The 3rd level length:"+metaList.getLength()); for (int k=0;k<metaList.getLength();k++) { Node meta = metaList.item(k); if (meta.getNodeType() == Node.ELEMENT_NODE) { System.out.println(meta.getNodeName()+":"+meta.getTextContent()); } } System.out.println(); } } } } catch (Exception e) { e.printStackTrace(); } } public static void traverseBySearch() { try { // 采用DOM解析xml文件 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse("user.xml"); Element rootElement = document.getDocumentElement(); NodeList nodeList = rootElement.getElementsByTagName("name"); if (nodeList != null) { for (int i=0;i<nodeList.getLength();i++) { Element element = (Element) nodeList.item(i); System.out.println(element.getNodeName()+"="+element.getTextContent()); } } } catch (Exception e) { e.printStackTrace(); } } }
public class DomWriter { public static void main(String[] args) { try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); // 创建一个Document节点 Document document = documentBuilder.newDocument(); if (document != null) { Element docx = document.createElement("document"); Element element = document.createElement("element"); element.setAttribute("type","paragraph"); element.setAttribute("alignment","left"); Element object = document.createElement("object"); object.setAttribute("type","text"); Element text = document.createElement("text"); text.appendChild(document.createTextNode("abcdefg")); Element bold = document.createElement("bold"); bold.appendChild(document.createTextNode("true")); object.appendChild(text); object.appendChild(bold); element.appendChild(object); docx.appendChild(element); document.appendChild(docx); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(document); // 定义目标文件 File file = new File("dom_result.xml"); StreamResult result = new StreamResult(file); //将xml内容写入到文件中 transformer.transform(source,result); System.out.println("write xml file successfully"); } } catch (Exception e) { e.printStackTrace(); } } }
XML解析(SAX方法)
-
Simple API for XML
- 采用事件/流模型来解析XML文档,更快速、更轻量
- 有选择的解析和访问,不像DOM加载整个文档,内存要求较低
- SAX对XML文档的解析为一次性读取,不创建/不存储文档对象,很难同时访问文档中的多处数据
- 推模型。当它每发现一个节点就引发一个事件,而我们需要编写这些事件的处理程序。关键类:DefaultHandler
- SAX的五个回调方法:
- startDocument 文档开始解析;
- endDocument文档结束解析;
- startElement开始访问元素;
- endElement结束访问元素;
- characters访问元素正文
-
示例
public class SAXReader { public static void main(String[] args) throws SAXException, IOException { XMLReader parser = XMLReaderFactory.createXMLReader(); BookHandler bookHandler = new BookHandler(); parser.setContentHandler(bookHandler); parser.parse("books.xml"); System.out.println(bookHandler.getNameList()); } } class BookHandler extends DefaultHandler { private List<String> nameList; private boolean title = false; public List<String> getNameList() { return nameList; } @Override public void startDocument() throws SAXException { System.out.println("Start parsing document..."); nameList = new ArrayList<String>(); } @Override public void endDocument() throws SAXException { System.out.println("End"); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("title")) { title=true; } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if(title) { title=false; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if(title) { String bookTitle = new String(ch, start, length); System.out.println("Book title: "+bookTitle); nameList.add(bookTitle); } } }
XML解析(Stax方法)
-
Streaming API for XML
- 流模型中的拉模型
- 在遍历文档时,会把感兴趣的部分从读拉取器中拉出,不需要引发事件,允许我们选择性地处理节点。这大大提高了灵活性,以及整体效率。
- 两套处理API
- 基础指针的API,XMLStreamReader
- 基于迭代器的API,XMLEventReader
-
示例
public class StaxReader { public static void main(String[] args) { StaxReader.readByStream(); System.out.println("======分割线======"); StaxReader.readByEvent(); } // 流模式 public static void readByStream() { String xmlFile = "books.xml"; XMLInputFactory factory = XMLInputFactory.newFactory(); XMLStreamReader streamReader = null; try { streamReader=factory.createXMLStreamReader(new FileReader(xmlFile)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (XMLStreamException e) { e.printStackTrace(); } // 基于指针遍历 try { while (streamReader.hasNext()) { int event = streamReader.next(); if (event== XMLStreamConstants.START_ELEMENT) { if("title".equalsIgnoreCase(streamReader.getLocalName())) { System.out.println("title:" + streamReader.getElementText()); } } } streamReader.close(); } catch (XMLStreamException e) { e.printStackTrace(); } } // 事件模式 public static void readByEvent() { String xmlFile = "books.xml"; XMLInputFactory factory = XMLInputFactory.newFactory(); boolean titleFlag = false; try { // 创建基于迭代器的事件读取器对象 XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(xmlFile)); // 遍历Event迭代器 while (eventReader.hasNext()) { XMLEvent event=eventReader.nextEvent(); // 如果事件对象是元素的开始 if (event.isStartElement()) { // 转换成开始元素事件对象 StartElement start = event.asStartElement(); // 打印元素标签的本地名称 String name = start.getName().getLocalPart(); // System.out.println(name); if (name.equals("title")) { titleFlag = true; System.out.print("title:"); } // 取得所有属性 Iterator attrs = start.getAttributes(); while (attrs.hasNext()) { // 打印所有属性信息 Attribute attr = (Attribute)attrs.next(); // System.out.println(":"+attr.getName().getLocalPart()+"="+attr.getValue()); } // System.out.println(); } // 如果事件对象是正文 if (event.isCharacters()) { String s = event.asCharacters().getData(); if (s !=null && s.trim().length()>0 && titleFlag) { System.out.println(s.trim()); } } // 如果事件对象时元素的结束 if (event.isEndElement()) { EndElement end = event.asEndElement(); String name = end.getName().getLocalPart(); if (name.equals("title")) { titleFlag = false; } } } eventReader.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (XMLStreamException e) { e.printStackTrace(); } } }
Json简介及解析
-
JSON
- JavaScript Object Notation, JS对象表示法
- 是一种轻量级的数据交换格式
- 类似XML,更小、更快、更易解析
- 最早用于Javascript,容易解析,最后推广到全语言
- 尽管使用Javascript语法,但是独立于编程语言
-
JSONObject和JSONArray
- 名称/值对。如“firstName":"Jhon”
- JSON对象:{'name':'Jo', 'email':'a@b.com'}
- 数据在键值对中
- 数据由逗号分隔
- 花括号保存对象
-
JSON数组
-
方括号保存数组
[{'name':'Jo', 'email':'a@b.com'}, {'name':'Jo', 'email':'a@b.com'}]
-
-
Java的JSON处理
-
org.json:JSON官方推荐的解析类
简单易用,通用性强,复杂功能欠缺
-
GSON:Google出品
基于反射,可以实现JSON对象、JSON字符串和Java对象互转
-
Jackson:号称最快的JSON处理器
简单易用,社区更新和发布速度比较快
-
-
JSON主要用途
- JSON生成
- JSON解析
- JSON校验
- 和Java Bean对象进行互解析
- 具有一个无参的构造函数
- 可以包括多个属性,所有属性都是private
- 每个属性都有相应的Getter/Setter方法
- Java Bean用于封装数据,又可称为POJO(Plain Old Java Object)
-
示例
org.json
public class OrgJsonTest { public static void main(String[] args) { testJsonObject(); System.out.println("======分割线======"); testJsonFile(); } public static void testJsonObject() { // 构造对象 Person p = new Person(); p.setName("Tom"); p.setAge(20); p.setScores(Arrays.asList(60,70,80)); // 构造JSONObject对象 JSONObject obj = new JSONObject(); obj.put("name",p.getName()); obj.put("age",p.getAge()); obj.put("scores",p.getScores()); System.out.println(obj); System.out.println("name: "+obj.getString("name")); System.out.println("age: "+obj.getInt("age")); System.out.println("scores: "+obj.getJSONArray("scores")); } public static void testJsonFile() { File file = new File("books.json"); try { FileReader reader = new FileReader(file); // 读取文件内容到JSONObject对象中 int fileLen = (int)file.length(); char[] chars = new char[fileLen]; reader.read(chars); String s = String.valueOf(chars); JSONObject jsonObject = new JSONObject(s); // 开始解析JSONObject对象 JSONArray books = jsonObject.getJSONArray("books"); List<Book> bookList = new ArrayList<>(); for(Object book:books) { // 获取单个JSONObject对象 JSONObject bookObject = (JSONObject)book; Book book1 = new Book(); book1.setAuthor(bookObject.getString("author")); book1.setYear(bookObject.getString("year")); book1.setTitle(bookObject.getString("title")); book1.setPrice(bookObject.getInt("price")); book1.setCategory(bookObject.getString("category")); bookList.add(book1); } for(Book book:bookList) { System.out.println(book.getAuthor()+", "+book.getTitle()); } } catch (Exception e) { e.printStackTrace(); } } }
Gson
public class GsonTest { public static void main(String[] args) { testJsonObject(); System.out.println("======分割线======"); testJsonFile(); } public static void testJsonObject() { //构造对象 Person p = new Person(); p.setName("Tom"); p.setAge(20); p.setScores(Arrays.asList(60,70,80)); //从Java对象到JSON字符串 Gson gson = new Gson(); String s = gson.toJson(p); System.out.println(s); //从JSON字符串到Java对象 Person p2 = gson.fromJson(s, Person.class); System.out.println(p2.getName()); System.out.println(p2.getAge()); System.out.println(p2.getScores()); //调用GSON的JsonObject JsonObject json = gson.toJsonTree(p).getAsJsonObject(); System.out.println(json.get("name")); System.out.println(json.get("age")); System.out.println(json.get("scores")); } public static void testJsonFile() { Gson gson = new Gson(); File file = new File("books2.json"); try { FileReader reader = new FileReader(file); List<Book> books = gson.fromJson(reader,new TypeToken<List<Book>>(){}.getType()); for(Book book:books) { System.out.println(book.getAuthor()+", "+book.getTitle()); } } catch (Exception e) { e.printStackTrace(); } } }
JSON和XML比较
- 都是数据交换格式,可读性强,可扩展性高
- 大部分的情况下,JSON更具优势(编码简单,转换方便),而且JSON字符串长度一般小于XML,传输效率更高
- XML更加注重标签和顺序
- JSON会丢失顺序信息