XML值可扩展标记语言,是用来传输和存储数据的。
XMl的特定:
- XMl文档必须包含根元素。该元素是所有其他元素的父元素。XML文档中的元素形成了一颗文档树,树中的每个元素都可存在子元素。
- 所有XML元素都必须有关闭标签。
- XML标签对大小写敏感,并且所有属性值date都需加引号。
XML元素:
XMl元素是只从包括开始标签到结束标签的部分,元素可包含其他元素、文本或两者都包含,也可拥有属性。
XML解析
基础方法:DOM、SAX
DOM解析:平台无关的官方解析方式
SAX解析:Java中基于事件驱动的解析方式
扩展方法:JDOM、DOM4J (在基础方法上扩展的,只有Java能够使用的解析方式)
1.DOM解析
优点:
·形成了树结构,直观好理解
·解析过程中树结构保留在内存中方便修改
缺点:
·当xml文件较大时,对内存消耗比较大,容易影响解析性能,并造成内存溢出
import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.util.LinkedList; import java.util.List; /** * DOM 解析xml */ public class DOM { public static void main(String[] args) throws Exception { // 1.创建 DocumentBuilderFactory 对象 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); // 2.通过 DocumentBuilderFactory对象创建 DocumentBuilder对象 DocumentBuilder db = dbf.newDocumentBuilder(); // 3.使用 DocumentBuilder对象来加载xml Document document = db.parse("bean.xml"); System.out.println("----------------- DOM开始解析 xml -----------------"); // 获取 xml 文件的根节点 Element element = document.getDocumentElement(); getNoeMsg(element); System.out.println("\n\n----------------- DOM结束解析 xml -----------------"); } /** * 获取Node节点信息 * @param node */ public static void getNoeMsg(Node node){ if(node.getNodeType() == Node.ELEMENT_NODE){ System.out.print("<" + node.getNodeName()); getNodeAttrs(node); System.out.print(">\n"); NodeList nodeList = node.getChildNodes(); // 筛选出节点类型为ELEMENT_NODE 的节点 List<Node> list = getNodeList(nodeList); Node childNode; int len = list.size(); if(len == 0){ System.out.print(node.getTextContent() + "\n"); }else { for (int i = 0; i < len; i++){ if(list.get(i).getNodeType() == Node.ELEMENT_NODE){ childNode = list.get(i); getNoeMsg(childNode); } } } System.out.println("</" + node.getNodeName() + ">"); } } /** * 获取Node节点的属性信息 * @param node */ public static void getNodeAttrs(Node node){ NamedNodeMap attrs = node.getAttributes(); Node attr; if(attrs.getLength() != 0){ for (int i = 0, len = attrs.getLength(); i < len; i++){ attr = attrs.item(i); System.out.print(" " + attr.getNodeName() + "='"); System.out.print(attr.getNodeValue() + "'"); } } } /** * 筛选出节点类型为ELEMENT_NODE 的节点 * @param nodeList * @return */ public static List<Node> getNodeList(NodeList nodeList){ List<Node> list = new LinkedList<>(); for (int i = 0,len = nodeList.getLength(); i < len; i++){ if(nodeList.item(i).getNodeType() == Node.ELEMENT_NODE){ list.add(nodeList.item(i)); } } return list; } }
2.SAX解析
优点:
·采用事件驱动模式,对内存消耗比较小
·适用于只需处理xml中数据时
缺点:
·不易编码
·很难同时访问同一个xml中的多处不同数据
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public class SAX { public static void main(String[] args) throws Exception { // 1.创建SAXParserFactory对象 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); // 2.通过SAXParserFactory对象创建 SAXParser SAXParser saxParser = saxParserFactory.newSAXParser(); // 3.通过SAXParser加载xml,并传入 DefaultHandler 类型的对象进行解析 saxParser.parse("bean.xml", new SAXParserHandler()); } static class SAXParserHandler extends DefaultHandler{ /** * 解析xml开始执行方法 * @throws SAXException */ @Override public void startDocument() throws SAXException { super.startDocument(); System.out.print("============= SAX开始解析xml =============\n"); } /** * 解析xml结束执行方法 * @throws SAXException */ @Override public void endDocument() throws SAXException { super.endDocument(); System.out.print("\n============= SAX结束解析xml ============="); } /** * 解析节点开始执行方法 * @param uri * @param localName * @param qName * @param attributes * @throws SAXException */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); System.out.print("<" + qName); for (int i = 0,len = attributes.getLength(); i < len; i++){ System.out.print(" " + attributes.getQName(i) + "='"); System.out.print(attributes.getValue(i) + "'"); } System.out.print(">"); } /** * 解析节点结束执行方法 * @param uri * @param localName * @param qName * @throws SAXException */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); System.out.print("</" + qName + ">"); } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); String str = new String(ch, start, length); System.out.print(str); } } }
3.JDOM解析
特征:
·使用了具体类,不使用接口。
·API大量使用了Collections类,源码开源
import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.List; /** * <!-- 引入JDOM依赖包 --> * <dependency> * <groupId>org.jdom</groupId> * <artifactId>jdom</artifactId> * <version>1.1</version> * </dependency> */ public class JDOM { public static void main(String[] args) throws IOException, JDOMException { // 1.创建SAXBuilder对象 SAXBuilder saxBuilder = new SAXBuilder(); // 2.获取xml文件输入流 InputStream in = new FileInputStream("bean.xml"); // 3.通过SAXBuilder对象的build方法,将xml文件输入流添加到SAXBuilder对象中 Document document = saxBuilder.build(in); // 4.获取xml根节点 Element rootElement = document.getRootElement(); // 5.根据根节点解析xml printNodeMsg(rootElement); } public static void printNodeMsg(Element element){ System.out.print("<" + element.getName()); // 获取节点的属性 printAttrmsg(element); System.out.print(">\n"); List<Element> elements = element.getChildren(); for (Element e : elements){ if(e.getChildren().size() > 0){ printNodeMsg(e); }else { System.out.print("<" + e.getName()); printAttrmsg(e); System.out.print(">"); System.out.print(e.getValue()); System.out.print("</" + e.getName() + ">\n"); } } System.out.print("</" + element.getName() + ">\n"); } /** * 获取节点的属性 * @param element */ public static void printAttrmsg(Element element){ List<Attribute> attributes = element.getAttributes(); for (Attribute attribute : attributes){ System.out.print(" " + attribute.getName() + "='" + attribute.getValue() + "'"); } } }
4.DOM4J解析
特征:
·使用了接口和抽象基本类方法
·具有性能优异、灵活性好、功能强大和极端易用的特点。
·开源
import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.Iterator; /** * <!-- dom4j依赖包 --> * <dependency> * <groupId>dom4j</groupId> * <artifactId>dom4j</artifactId> * <version>1.6.1</version> * </dependency> */ public class DOM4J { public static void main(String[] args) throws FileNotFoundException, DocumentException { // 1.创建SAXReader对象 SAXReader saxReader = new SAXReader(); // 2.通过SAXReader对象的read方法,加载xml输入流 Document document = saxReader.read(new FileInputStream("bean.xml")); // 3.通过Document对象获取xml的根节点 Element rootElement = document.getRootElement(); // 4.通过根节点解析xml printNodeMsg(rootElement); } public static void printNodeMsg(Element element){ System.out.print("<" + element.getName()); // 获取节点的属性 printAttrmsg(element); System.out.print(">\n"); Iterator<Element> elementIterator = element.elementIterator(); Element e; while (elementIterator.hasNext()){ e = elementIterator.next(); if(e.elementIterator().hasNext()){ printNodeMsg(e); }else { System.out.print("<" + e.getName()); printAttrmsg(e); System.out.print(">"); System.out.print(e.getStringValue()); System.out.print("</" + e.getName() + ">\n"); } } System.out.print("</" + element.getName() + ">\n"); } /** * 获取节点的属性 * @param element */ public static void printAttrmsg(Element element){ Iterator<Attribute> attributeIterator = element.attributeIterator(); Attribute attribute; while (attributeIterator.hasNext()){ attribute = attributeIterator.next(); System.out.print(" " + attribute.getName() + "='" + attribute.getValue() + "'"); } } }