XML学习教程

1 篇文章 0 订阅
本文详细介绍了XML的定义、用途、以及在数据交互、配置文件(如MyBatis)中的应用。探讨了Java中处理XML的各种技术,如DOM、SAX、JDOM和DOM4J,并通过实例展示了它们的读写操作。此外,还讨论了XPath在XML解析中的重要作用,以及DOM和SAX解析器的优缺点。最后,文章提供了XPath的基本语法和运算符的概述。
摘要由CSDN通过智能技术生成

XML学习教程

xml是什么

xml是可扩展标记语言EXtensible Markup Language

XML 被设计用来传输和存储数据。

XML 不会做任何事情。XML 被设计用来结构化、存储以及传输信息。

<note>
	<to>George</to>
	<from>John</from>
	<heading>Reminder</heading>
	<body>Don't forget the meeting!</body>
</note>

第一行是 XML 声明。它定义 XML 的版本 (1.0) 和所使用的编码 (ISO-8859-1 = Latin-1/西欧字符集)。

下一行描述文档的根元素(像在说:“本文档是一个便签”):

接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body):

最后一行定义根元素的结尾:

XML 没什么特别的。它仅仅是纯文本而已。有能力处理纯文本的软件都可以处理 XML。

不过,能够读懂 XML 的应用程序可以有针对性地处理 XML 的标签。标签的功能性意义依赖于应用程序的特性。

上例中的标签没有在任何 XML 标准中定义过(比如 和 )。这些标签是由文档的创作者发明的。

这是因为 XML 没有预定义的标签。

在 HTML 中使用的标签(以及 HTML 的结构)是预定义的。HTML 文档只使用在 HTML 标准中定义过的标签(比如

等等)。

XML 允许创作者定义自己的标签和自己的文档结构。

XML 标签对大小写敏感。

xml使用场景

​ 数据交互

​ 虽然目前有json来替代xml作数据交互,但是对于一些老系统或者某些软件来说,xml的优先级还是更高

​ 配置文件(mybatis)

java操作xml

可使用技术

写操作

dom、dom4j、jdom、xstream、jaxb、spring ixm

读操作

sax、deqister、dom、dom4j、jdom、xstream、jaxb、spring ixm

术语解释

jaxp:java API For XML Process

​ java关于xml的api,关注如何站到某个元素内容

​ 主要由两类:

  • dom:Document Object Model

    • w3c推出的规范
  • sax:Simple API For XML Binding

jaxb:Java Architecture for XML Binding

关注xml和java Object之间的转化

oxm:Object XML Mapping

对象和xml间映射

具体应用

DOM

dom是jdk自带的xml处理程序。

DOM 分析器通过对XML文档的分析,把整个XML文档以一棵DOM树的形式存放在内存中,应用程序可以随时对DOM树中的任何一个部分进行访问与操作,也就是 说,通过DOM树,应用程序可以对XML文档进行随机访问。这种访问方式给应用程序的开发带来了很大的灵活性,它可以任意地控制整个XML文档中的内容。 然而,由于DOM分析器把整个XML文档转化成DOM树放在了内存中,因此,当XML文档比较大或者文档结构比较复杂时,对内存的需求就比较高。而且,对 于结构复杂的树的遍历也是一项比较耗时的操作。所以,DOM分析器对机器性能的要求比较高,实现效率不十分理想。

public void testRead() throws ParserConfigurationException, IOException, SAXException {
    //创建DocumentBuilder工厂
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    //通过工厂获得DocumentBuilder
    DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
    //通过DocumentBuilder获得
    Document parse = documentBuilder.parse("src\\main\\resources\\test.xml");
    NodeList list = parse.getElementsByTagName("link");
    for (int i = 0; i < list.getLength(); i++) {
        Element item = (Element) list.item(i);
        System.out.println(item.getAttribute("type"));
        System.out.println(item.getTagName());
        System.out.println(item.getFirstChild().getNodeValue());
    }
}

dom会将xml解析成下面这样的树。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eCBG3c6d-1636353899163)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211015142905106.png)]

通过xpath也可以查找到元素

@Test
public void testReadByXpath() throws Exception {
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
    Document document = documentBuilder.parse("src\\main\\resources\\test.xml");

    XPathFactory xPathFactory = XPathFactory.newInstance();
    XPath xPath = xPathFactory.newXPath();
    XPathExpression compile = xPath.compile("//link[@type='0']//text()");
    Node node = (Node) compile.evaluate(document, XPathConstants.NODE);
    System.out.println(node.getNodeValue());
}

通过dom也可以将对象转化成xml

@Test
public void testWrite() throws Exception {
    Document document = creatDocument();
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    DOMSource domSource = new DOMSource(document);
    FileOutputStream fileOutputStream = new FileOutputStream("src\\main\\resources\\test2.xml");
    StreamResult streamResult = new StreamResult(fileOutputStream);
    //设置字符编码
    transformer.setOutputProperty(OutputKeys.ENCODING,"utf-8");
    //设置美化换行
    transformer.setOutputProperty(OutputKeys.INDENT,"yes");
    transformer.transform(domSource,streamResult);
    fileOutputStream.close();
}
mybatis中的应用

org.apache.ibatis.session.SqlSessionFactoryBuilder中的build方法会调用parser.passer()方法,最后的调用是this.xpath.evaluate(expression, root, returnType);,使用xpath进行解析。(mybatis版本3.5.3)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yPWgwGYL-1636353899165)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211015171118118.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dVdQWlCO-1636353899172)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211015171213225.png)]

SAX

SAX分析器在对XML文档进行分析时,触发一系列的事件,应用程序通过事件处理函数实现对XML文档的访问。由于事件触发本身是有时序性的,因此,SAX分析器提供的是一种对XML文档的顺序访问机制,对于已经分析过的部分,不能再倒回去重新处理。

适用于只处理文件中的数据而不需要对文件做更改的情况。

使用sax处理重写DefaultHandler()类来处理数据

    public void saxTest()throws Exception{
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        SAXParser saxParser = saxParserFactory.newSAXParser();
        saxParser.parse("src\\main\\resources\\test.xml",new DefaultHandler(){
            @Override
            public void startDocument() throws SAXException {
                System.out.println("startDocument");
            }

            @Override
            public void endDocument() throws SAXException {
                System.out.println("endDocument");
            }

            @Override
            public void startElement(String uri, String localName,
                                     String qName, Attributes attributes) throws SAXException {
                System.out.print("<"+qName);
                for (int i = 0;i<attributes.getLength();i++){
                    System.out.print(" "+attributes.getQName(i)+"=\""+attributes.getValue(i)+"\"");
                }
                System.out.print(">");
            }

            @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));
            }
        });
    }

处理结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hb1PeFLs-1636353899173)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211018100451886.png)]

jdom

JDOM是处理XML的纯JAVA API。使用具体类而不用接口,既要生成大多数节点类型的实例,只要将一两个变元传入即可。是目前表现优秀的处理XML的JAVA API。

public static void parseXmlByJDOM(){
	   long begintime=System.currentTimeMillis();
	   File f=new File("students.xml");  
	   SAXBuilder builder=new SAXBuilder();
	   try {
		Document doc=builder.build(new FileInputStream(f));
		Element root=doc.getRootElement();
		System.out.println(root.getAttributeValue("class")+"-人数:--"+root.getAttributeValue("count"));
		
		List list=root.getChildren("student");
		for(int i=0;i<list.size();i++){
			Element ele=(Element)list.get(i);
			System.out.println("第"+(i+1)+"个学生");
			System.out.println(ele.getChildText("name")+"---"+ele.getChildText("age"));
		}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	    System.out.println("sax解析时间(毫秒)"+(System.currentTimeMillis()-begintime));
   }

dom4j

DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J。

目前org.dom4j还在维护,推荐使用orj.dom4j

<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.1.3</version>
</dependency>

在dom4j中xml也是采用树状存储

public void dom4jTestRead() throws Exception{
    SAXReader saxReader = new SAXReader();
    org.dom4j.Document document = saxReader.read(new File("src\\main\\resources\\test.xml"));
    org.dom4j.Element rootElement = document.getRootElement();
    System.out.println(rootElement);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CV4jUsQW-1636353899174)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211018103959202.png)]

DOM4J是 dom4j.org 出品的一个开源 XML 解析包。DOM4J应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP。

DOM4J 使用起来非常简单。只要你了解基本的 XML-DOM 模型,就能使用。

Dom:把整个文档作为一个对象。

DOM4J 最大的特色是使用大量的接口。它的主要接口都在org.dom4j里面定义:

Attribute定义了 XML 的属性。
Branch指能够包含子节点的节点。如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为
CDATA定义了 XML CDATA 区域
CharacterData是一个标识接口,标识基于字符的节点。如CDATA,Comment, Text.
Comment定义了 XML 注释的行为
Document定义了XML 文档
DocumentType定义 XML DOCTYPE 声明
Element定义XML 元素
ElementHandler定义了Element 对象的处理器
ElementPath被 ElementHandler 使用,用于取得当前正在处理的路径层次信息
Entity定义 XML entity
Node为dom4j中所有的XML节点定义了多态行为
NodeFilter定义了在dom4j 节点中产生的一个滤镜或谓词的行为(predicate)
ProcessingInstruction定义 XML 处理指令
Text定义 XML 文本节点
Visitor用于实现 Visitor模式
XPath在分析一个字符串后会提供一个 XPath 表达式

接口之间的继承关系如下:

interface java.lang.Cloneable

interface org.dom4j.Node

​ interface org.dom4j.Attribute

​ interface org.dom4j.Branch

​ interface org.dom4j.Document

​ interface org.dom4j.Element

​ interface org.dom4j.CharacterData

​ interface org.dom4j.CDATA

​ interface org.dom4j.Comment

​ interface org.dom4j.Text

​ interface org.dom4j.DocumentType

​ interface org.dom4j.Entity

​ interface org.dom4j.ProcessingInstruction

遍历xml节点

​ 对Document对象调用getRootElement()方法可以返回代表根节点的Element对象。拥有了一个Element对象后,可以对该对象调用elementIterator()方法获得它的子节点的Element对象们的一个迭代器。使用(Element)iterator.next()方法遍历一个iterator并把每个取出的元素转化为Element类型。

public boolean isOnly(String catNameEn, HttpServletRequest request,  
        String xml) {  
    boolean flag = true;  
    String path = request.getRealPath(""); 
    Document doc = load(path + "/" + xml);  
    Element root = doc.getRootElement();  
    for (Iterator i = root.elementIterator(); i.hasNext();) {  
        Element el = (Element) i.next(); 
        if (catNameEn.equals(el.elementTextTrim("engName"))) { 
            flag = false;  
            break;  
        }  
    }  
    return flag;  
}

总结:

dom

优点:

形成树状结构,直观,容易理解

整棵树加载到内存,允许对XML文档进行随机访问

解析过程存储在内存中,方便修改

缺点:

整个XML文档必须一次解析完

当文件较大时对内存消耗较大

一般的DOM节点对于必须为所有节点创建对象的对象类型绑定不太理想

最适合于:

需要修改XML文档的应用程序或XSLT应用程序(不可用于只读XML的应用程序)

sax

优点:

采用事件驱动,无需将整个文档加载到内存,因而内存消耗少

适用于只需要处理xml中数据时

堆模型允许注册多个ContentHandler

缺点:

没有内置的文档导航支持

不易编码

不能够随机访问XML文档

很难同时访问同一个xml中的多处不同数据

不支持名字空间作用域

最适合于:

只从XML读取数据的应用程(不可用于操作或修改XML文档)

JDOM

优点:

是基于树的处理XML的Java API,把树加载在内存中

没有向下兼容的限制,因此比DOM简单

速度快,缺陷少

具有SAX的JAVA规则
缺点:

不能处理大于内存的文档

JDOM表示XML文档逻辑模型。不能保证每个字节真正变换。

针对实例文档不提供DTD与模式的任何实际模型。

不支持与DOM中相应遍历包
最适合于:

JDOM具有树的便利,也有SAX的JAVA规则。在需要平衡时使用

dom4j

优点:
大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
支持XPath。
有很好的性能.
缺点:
大量使用了接口,API较为复杂。

xpath语法

1、选取节点

XPath 使用路径表达式在 XML 文档中选取节点,节点是沿着路径或者 step 来选取的。

常见的路径表达式:

表达式描述
nodename选取当前节点的所有子节点
/从根节点选取
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
.选取当前节点
选取当前节点的父节点
@选取属性

实例

路径表达式结果
bookstore选取 bookstore 元素的所有子节点
/bookstore选取根元素 bookstore
bookstore/book选取bookstore 下名字为 book的所有子元素
//book选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book选取bookstore 下名字为 book的所有后代元素,而不管它们位于 bookstore 之下的什么位置。
//**@**lang选取所有名为 lang 的属性。

2、谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

谓语被嵌在方括号中。

实例

常见的谓语的一些路径表达式:

路径表达式结果
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()< 3]选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=‘eng’]选取所有 title 元素,要求这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00]选取所有 bookstore 元素的 book 元素,要求book元素的子元素 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title选取所有 bookstore 元素中的 book 元素的 title 元素,要求book元素的子元素 price 元素的值须大于 35.00

3、选取未知节点

XPath 通配符可用来选取未知的 XML 元素。

通配符描述
*匹配任何元素节点
@*匹配任何属性节点
node()匹配任何类型的节点

实例

路径表达式结果
/bookstore/*选取 bookstore 元素的所有子节点
//*选取文档中的所有元素
//title[@*]选取所有带有属性的 title 元素。

4、选取若干路径

通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

实例

路径表达式结果
//book/title | //book/price选取所有 book 元素的 title 和 price 元素。
//title | //price选取所有文档中的 title 和 price 元素。
/bookstore/book/title**|**//price选取所有属于 bookstore 元素的 book 元素的title 元素,以及文档中所有的 price 元素。

5、XPath 轴

轴可定义某个相对于当前节点的节点集。

轴名称结果
ancestor选取当前节点的所有先辈(父、祖父等)
ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身
attribute选取当前节点的所有属性
child选取当前节点的所有子元素。
descendant选取当前节点的所有后代元素(子、孙等)。
descendant-or-self选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following选取文档中当前节点的结束标签之后的所有节点。
namespace选取当前节点的所有命名空间节点
parent选取当前节点的父节点。
preceding选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling选取当前节点之前的所有同级节点。
self选取当前节点。

6、路径

位置路径可以是绝对的,也可以是相对的。

绝对路径起始于正斜杠( / ),而相对路径不会这样。在两种情况中,位置路径均包括一个或多个步,每个步均被斜杠分割:

/step/step/...
step/step/...

每个步均根据当前节点集之中的节点来进行计算。

轴(axis):定义所选节点与当前节点之间的树关系

节点测试(node-test):识别某个轴内部的节点

零个或者更多谓语(predicate):更深入地提炼所选的节点集

步的语法轴名称::节点测试[谓语]

实例

例子结果
child::book选取所有属于当前节点的子元素的 book 节点
attribute::lang选取当前节点的 lang 属性
child:: *选取当前节点的所有子元素
attribute:: *选取当前节点的所有属性
child::text()选取当前节点的所有文本子节点
child::node()选取当前节点的所有子节点
descendant::book选取当前节点的所有 book 后代
ancestor::book选择当前节点的所有 book 先辈
ancestor-or-self::book选取当前节点的所有book先辈以及当前节点(假如此节点是book节点的话)
child:: */child::price选取当前节点的所有 price 孙。

7、XPath 运算符

运算符描述实例返回值
|计算两个节点集//book | //cd返回所有带有 book 和 ck 元素的节点集
+加法6 + 410
-减法6 - 42
*乘法6 * 424
div除法8 div 42
=等于price=9.80如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 fasle。
!=不等于price!=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 fasle。
<小于price<9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 fasle。
<=小于或等于price<=9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 fasle。
>大于price>9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 fasle。
>=大于或等于price>=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 fasle。
orprice=9.80 or price=9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 fasle。
andprice>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 fasle。
mod计算除法的余数5 mod 21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值