java-xml基础入门解析

    科技2024-04-04  97

    xml 概念

    XML(EXtensible Markup Language) ,可拓展标记语言

    标记,指的的是标记语言,也称标签语言,可以用一系列的标签来对数据进行描述。

    例如, tom

    拓展,指的是用户可以自定义标签

    作用

    XML可以作为数据传输的标准xml可以作为配置文件

    xml语法

    XML 声明文件的可选部分,如果存在需要放在文档的第一行,如下所示:

    <?xml version="1.0" encoding="utf-8"?>

    描述了XML的版本,以及XML文档所使用的编码

    元素

    元素,指的是xml中的标记.这种标记也被称为标签,节点

    命名规范

    不能以数字或部分标点符号开头

    不能包含空格和特定的几个符号

    标签必须成对出现,不允许缺省结束标签

    根元素有且只有一个 大小写敏感

    允许多层嵌套但是不允许交叉嵌套

    xml 必须包含根元素

    元素可以包含标签体,也可以不包含标签体

    xml 标签对大小写敏感

    xml 中第一行,文档声明部分,固定写法,不需要关闭标签

    属性

    基本格式

    <?xml version="1.0" encoding="utf-8"?> <root> <person sex="female" age='18' email='briup@briup.com'></person> </root>

    基本格式 <元素名 属性名=“属性值”>

    不论是使用子标签还是属性 描述数据都是合格的

    实体

    在 XML 中,一些字符拥有特殊的意义,在XML文档中,是不能直接使用的。

    例如,如果把字符 “<” 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C0boFtDi-1602046595202)(E:\学习\Java2020\image\image-20200909143207725.png)]

    自定义实体

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sKNOmajT-1602046595204)(E:\学习\Java2020\image\image-20200909143258886.png)]

    xml约束

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ItvXY8yM-1602046595206)(E:\学习\Java2020\image\image-20200909143355951.png)]

    约束语法

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hx3mJ3FV-1602046595208)(E:\学习\Java2020\image\image-20200909143426999.png)]

    ## XML解析

    xml的解析方法一般有两种

    DOM解析

    DOM,(Document Object Model)文档对象模型,是 W3C 组织推荐的处理 XML 的一种方式。

    使用DOM方式解析,要求解析器把整个XML文档装载到一个Document对象中。Document对象包含文档

    元素,即根元素,根元素包含N个子元素。

    根据DOM的定义,XML 文档中的每个元素都是一个节点(Node):

    XML文档只有一个根节点

    XML中每个元素都是一个元素节点

    XML中每个文本都是一个文本节点

    XML中每个属性都是一个属性节点

    XML中每个注释都是一个注释节点

    使用DOM解析方式,XML文档的结构关系,在内存的对象(document)中依然存在

    但如果XML文档过大,那么需要把整个XML文档装载进内存,这时候会对内存空间要求比较高

    SAX解析

    SAX,(Simple API for XML)它不是W3C标准,但它是 XML 社区事实上的标准,因为使用率也比较高,

    几乎所有的 XML 解析器都支持它。

    使用SAX方式解析,每当读取一个开始标签、结束标签或者文本内容的时候,都会调用我们重写的一个

    指定方法,该方法中编写当前需要完成的解析操作。直到XML文档读取结束,在整个过程中,SAX解析

    方法不会在内存中保存节点的信息和关系。

    使用SAX解析方式,不会占用大量内存来保存XML文档数据和关系,效率高。

    但是在解析过程中,不会保存节点信息和关系,并且只能从前往后,顺序读取、解析。

    java解析xml

    JAXP (Java API for XMLProcessing),是JavaSE-API的一部分,它由javax.xml、org.w3c.dom 、 org.xml.sax 包及其子包组成

    也就是说,不借助于第三方jar包,使用JDK自带的API,就可以完成对XML文档的解析

    XML解析实例

    jaxp中的DOM解析

    需要解析class.xml

    <?xml version="1.0" encoding="UTF-8"?> <students> <stu id="2022001"> <name>王五</name> <age>23</age> </stu> <stu id="2022002"> <name>李四</name> <age>20</age> </stu> </students>

    实例代码

    package com.lut.day2; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class Test { public static void main(String[] args) throws Exception { // 获取documentBuilderFactory DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 获取documentBuilder DocumentBuilder builder = factory.newDocumentBuilder(); // 获取xmlDocument Document doc = builder.parse(new File("src/test.xml")); // 获取根节点 Element root = doc.getDocumentElement(); List<Student> list = new ArrayList<>(); NodeList nodeList = root.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); // 如果为文本节点且节点内容为空格,就进行下一次 if (node.getNodeType() == Node.TEXT_NODE) { if (node.getNodeValue().trim().length() == 0) { continue; } } if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals("stu")) { // 获取属性列表 NamedNodeMap attributes = node.getAttributes(); String id = ""; String name = ""; String age = ""; // 循环变量拿到每一个属性 for (int j = 0; j < attributes.getLength(); j++) { // 强制转换为Attr类型的对象,表示属性 Attr attr = (Attr) attributes.item(j); if(attr.getName()=="id") { id = attr.getValue(); } } // 获取子节点列表 NodeList nodeList2 = node.getChildNodes(); for(int j=0;j<nodeList2.getLength();j++) { Node node2 = nodeList2.item(i); // 如果为文本节点且节点内容为空格,就进行下一次 if (node2.getNodeType() == Node.TEXT_NODE) { if (node2.getNodeValue().trim().length() == 0) { continue; } } // 如果为name标签 if (node2.getNodeType()==Node.ELEMENT_NODE && node2.getNodeName().equals("name")) { // 获取他的唯一一个Text子节点 Node text = node2.getChildNodes().item(0); name = text.getNodeValue(); } // 如果为age标签 if (node2.getNodeType()==Node.ELEMENT_NODE && node2.getNodeName().equals("age")) { // 获取他的唯一一个Text子节点 Node text = node2.getChildNodes().item(0); age = text.getNodeValue(); } } list.add(new Student(id, name, age)); } } System.out.println(list); } } class Student { String id; String name; String age; public Student(String id, String name, String age) { this.id = id; this.age = age; this.name = name; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", age=" + age + "]"; } }

    Sax解析

    JAXP中的SAX解析的步骤:

    获取SAXParserFactory工厂类对象, SAXParserFactory.newInstance()使用工厂对象,创建出SAX解析器, saxParserFactory.newSAXParser()调用解析器的 parse() 解析xml文件,然后重写DefaultHandler类中的方法,进行事件处理 saxParser.parse(filePath, new DefaultHandler(){…} package com.briup.demo; 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 Test { public static void main(String[] args) { Test dom = new Test(); String filePath = "src/com/briup/demo/class.xml"; dom.saxParse(filePath); } public void saxParse(String filePath) { //获取SAXParserFactory工厂类对象 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); try { //使用工厂对象,创建出SAX解析器 SAXParser saxParser = saxParserFactory.newSAXParser(); //解析xml文件,重写DefaultHandler类中的方法,进行事件处理 saxParser.parse(filePath, new DefaultHandler() { //当解析器解析到xml文档开头的时候,调用该方法 @Override public void startDocument() throws SAXException { System.out.println("开始解析xml文档"); } //当解析器解析到xml文档结束的时候,调用该方法 @Override public void endDocument() throws SAXException { System.out.println(); System.out.println("结束解析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 { System.out.println("节点:"+qName+"解析开始"); if(attributes.getLength()>0) { System.out.print(" 属性列表:"); for(int i=0;i<attributes.getLength();i++) { String attrName = attributes.getQName(i); String attrValue = attributes.getValue(i); System.out.print(attrName+"="+attrValue+" "); } System.out.println(); } } /** * 当解析器解析到一个结束标签的时候,调用该方法 * @param uri 命名空间 * @param localName 本地名称(不带前缀) * @param qName 限定的名称(带有前缀) * @throws SAXException */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("节点:"+qName+"解析结束"); } //当解析器解析到文件值的时候,调用该方法 @Override public void characters(char[] ch, int start, int length) throwSAXException { String str = new String(ch,start,length); if(!"".equals(str.trim())) { System.out.println("文本节点:"+str); } } }); } catch (Exception e) { e.printStackTrace(); } } }

    案例

    package com.briup.demo; 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 Test { public static void main(String[] args) { Test dom = new Test(); String filePath = "src/com/briup/demo/class.xml"; dom.saxParse(filePath); } public void saxParse(String filePath) { //获取SAXParserFactory工厂类对象 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); try { //使用工厂对象,创建出SAX解析器 SAXParser saxParser = saxParserFactory.newSAXParser(); //解析xml文件,重写DefaultHandler类中的方法,进行事件处理 saxParser.parse(filePath, new DefaultHandler() { @Override public void startDocument() throws SAXException { System.out.println("<?xml version='1.0' encoding='utf-8'? >"); } @Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { StringBuilder sb = new StringBuilder(); sb.append("<").append(qName); for(int i = 0; i < atts.getLength(); i++) { sb.append(" "); sb.append(atts.getQName(i)); sb.append("="); sb.append("'"); sb.append(atts.getValue(i)); sb.append("'"); } sb.append(">"); System.out.print(sb.toString()); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { System.out.print("</" + qName + ">"); } @Override public void characters(char[] ch, int start, int length) throws SAXException { System.out.print(new String(ch, start, length)); } }); } catch (Exception e) { e.printStackTrace(); } } }

    Dom4j解析

    需要导入dom4j的依赖

    案例

    public class Test { public static void main(String[] args) { Test test = new Test(); String filePath = "src/com/briup/demo/class.xml"; try { Document document = test.parse(new File(filePath)); test.handler1(document); } catch (Exception e) { e.printStackTrace(); } } public Document parse(File file) throws DocumentException { SAXReader reader = new SAXReader(); Document document = reader.read(file); return document; } public void handler1(Document document) { Element root = document.getRootElement(); System.out.println("-----获取根节点下面所有的子节点(儿子节点)-----"); // 获取根节点下面所有的子节点(儿子节点) for (Iterator<Element> it = root.elementIterator(); it.hasNext();) { Element element = it.next(); System.out.println(element.getName()); } System.out.println("-----获取根节点下面指定名称的子节点(儿子节点)-----"); // 获取根节点下面指定名称的子节点(儿子节点) for (Iterator<Element> it = root.elementIterator("stu"); it.hasNext();) { Element element = it.next(); System.out.println(element.getName()); } System.out.println("-----获取根节点中的所有属性-----"); // 获取根节点中的所有属性 for (Iterator<Attribute> it = root.attributeIterator(); it.hasNext();) { Attribute attribute = it.next(); System.out.println(attribute.getName()+"="+attribute.getValue()); } } } //运行结果: -----获取根节点下面所有的子节点(儿子节点)----- stu stu teacher -----获取根节点下面指定名称的子节点(儿子节点)----- stu stu -----获取根节点中的所有属性----- sid=1 sname=briup

    dom4j提供了两个方法支持XPath搜索 List selectNodes(String expr); Node selectSingleNode(String expr);

    Xpath表达式的几种写法

    第一种形式: /AAA/BBB/CCC:表示层级结构,表示AAA下面BBB下面的所有CCC

    第二种形式: //BBB:选择文档中所有的BBB元素

    第三种形式: /AAA/BBB/:选择目录下的所有元素 //:选择所有的元素 //AAA[1]/BBB:选择第一个AAA下的BBB元素

    第四种形式: //AAA/BBB[1]:选择所有AAA的第一个BBB元素 //AAA/BBB[last()]:选择所有AAA的最后一个BBB元素

    第五种形式: //@id:选择所有的id属性 //BBB[@id]:选择具有id属性的BBB元素

    第六种形式: //BBB[@id=‘b1’] :选择含有属性id并且其值为b1的BBB元素

    使用DOM4j创建一个xml文档

    public class Test { public static void main(String[] args) { Test test = new Test(); try { test.createXML(test.createDocument()); } catch (Exception e) { e.printStackTrace(); } } public Document parse(File file) throws DocumentException { SAXReader reader = new SAXReader(); Document document = reader.read(file); return document; } @SuppressWarnings("all") public Document createDocument() { Document document = DocumentHelper.createDocument(); Element root = document.addElement("root"); Element author1 = root.addElement("author") .addAttribute("name", "briup1") .addAttribute("location", "上海") .addText("hello"); Element author2 = root.addElement("author") .addAttribute("name", "briup2") .addAttribute("location", "北京") .addText("world"); return document; } public void createXML(Document document) { try { FileWriter out = new FileWriter("src/com/briup/demo/my.xml"); document.write(out); out.close(); } catch (IOException e) { e.printStackTrace(); } } }
    Processed: 0.011, SQL: 8