背景
在Java开发的过程中,我们经常需要和配置文件打交道,其中接触最多的就是XML。从最初学习 JavaWeb 时在 Tomcat 中配置servlet,到后来接触Spring框架并在XML中编写各种配置,XML一直是不可或缺的一部分。然而,XML的复杂性给我留下了深刻的印象:它有众多的标签和属性,而且每种场景下的标签和属性都有所不同。更令人困惑的是,标签中还存在大量的xmlns属性,后面跟着一串网址,让人摸不着头脑。因此,每次配置Tomcat或Spring时,我总是习惯先在网上找一个配置文件模板,然后稍作修改就使用,对XML本身并没有深入的了解。最近正好有一些空闲的时间,就把这一块的空白好好填一填了。
XML 初体验
下面是一个Tomcat的配置文件示例,对于学习过JavaWeb的同学来说,这个配置应该不会陌生。它定义了与servlet相关的一些信息:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!--servlet与servlet-mapping标签需同时使用--><!--创建servlet标签--><servlet><!--给指定的servlet类起一个名字--><servlet-name>demo01</servlet-name><!--servlet类的全限定路径--><servlet-class>demo</servlet-class><!--servlet初始化加载优先级(0~10)--><load-on-startup>0</load-on-startup></servlet><!--创建servlet映射标签--><servlet-mapping><!--映射到哪个servlet,与上面一致--><servlet-name>demo01</servlet-name><!--客户端访问路径 localhost:8080/项目名称/demo--><url-pattern>/demo</url-pattern></servlet-mapping></web-app>
而在Spring框架中,我们则使用另一种XML配置文件来定义bean的相关信息。下面是一个简单的Spring配置文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="Demo01" class="com.hello.Demo01"></bean>
</beans>
在这个配置文件中,我们定义了一个id为"Demo01"的bean,它的类是"com.hello.Demo01"。通过这个配置文件,Spring框架能够创建和管理这个bean的实例。
XML 元素解析
通过前面两个 XML 文件的例子我们对于 XML 的格式有了一个大概的了解,下面我们就来一起分析一下 XML 中的元素,以及其代表的意义。
XML声明
首先是第一部分: <?xml version="1.0" encoding="UTF-8"?>
这是 XML 的声明部分,格式是 <?xml ?>
,version
是声明标签的属性,代表当前使用的 XML 格式的版本是 1.0
。同理 encoding="UTF-8"
代表当前文件所使用的编码是 UTF-8
。到这里,
我对于 XML 的声明产生了一些疑问,然后针对这些问题去查找了一些资料,以问答的形式分享给大家,不对的地方希望大家能指出。
Q:version 的取值哪些,也就是说目前 XML 存在哪些版本?
A:目前有两个版本 1.0 和 1.1,目前大多数应用程序仍然主要使用 1.0.
Q:encoding 的取值有哪些,即支持哪些编码格式?
A:主流的格式都支持,例如 UTF-8、UTF-16、ISO-8859-1、GB2312、GBK 等等等等。UTF-8 是最常用也是最推荐的。
Q:XML 声明的部分是不是只有 version 和 encoding 两个属性?
**A:其实还有一个属性 standalone ,它的取值是 “yes” 或 “no”,表示该文档是否独立(是否依赖外部资源),如果值为"yes",则意味着该文档不需要外部资源即可被解析;如果值为"no"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Q:声明是不是只能写在第一行?
A:推荐写在第一行,但是并没有严格的限制,只要它出现在文档开始处,且在任何元素或注释之前即可
Q:XML 文件一定要写声明吗?
A:推荐写声明,毕竟可以通过声明指定文件的编码类型,但是没有强制要求,不写也可以。
标签
在 XML 最重要也是最主要的元素就是标签,什么是标签呢?
在 tomcat 配置文件中 <web-app>
是标签,在 spring 配置文件中,<beans>
也是标签,标签就是这样被尖括号包围的单词,它总是成对出现,例如 <web-app>
和 </web-app>
, <beans>
和</beans>
。
**在 XML 中必须要有一对根标签,所有的标签和信息都要在根标签里面,**如下的情况就不是一个 XML 格式的文件:
<name>张三</name>
<age>3</age>
如果只有一对 name 标签,或者是 age 标签都对。因为只有一对标签的情况下,那对标签就是根标签。两对标签并行的情况就是错的,没有办法识别谁是根标签,如果要改成正确的形式,要么在外面新增一个根标签:
<xxx><name>张三</name><age>3</age>
</xxx>
要么把其中一个标签放到另一个标签里面:
<name>张三<age>3</age>
</name>
相对于限制,XML 更多的是自由,**在 XML 中所有的标签都必须自定义,它没有所谓的官方标签,**这意味着开发人员可以根据需要创建自己的标签,以适应特定的数据结构和应用程序需求。也就是说在 Tomcat 中的 <web-app>
标签是 Tomcat 定义的,它的作用只能体现在 Tomcat 中,而在 Spring 中的 <beans>
也是 Spring 中定义的,换个地方它可能就没有作用了。为什么是可能?因为你也可以定义一样的标签然后赋予它意义。
在 XML 中标签只能完整包含其他标签,不能只包含标签的一部分。例如:
<name>张三<age>3</age><aaa><bbb></aaa></bbb>
</name>
试图让一个标签只包含另一个标签的开始部分或结束部分,这在 XML 中是不允许的。
标签属性
在 XML 中的标签上也可以附加一些额外信息,它们以 key=“value” 的形式出现,这就是标签的属性,与标签一样是必须由用户自定义的。例如上文中出现的 bean 标签:<bean id="Demo01" class="com.hello.Demo01"></bean>
,其中 id 和 class 就是 bean 标签的属性,它们是 bean 标签的附加信息。
命名空间
在上面的配置文件中我们注意到,根标签上有 xmlns 属性定义命名空间。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0">
xmlns 的含义是 XML NameSpace 的缩写,即 XML 文件的命名空间,那么这个是干嘛用的呢?
在 XML 中,在不同的场景下可能存在含义不一样但是名称相同的标签,如果要在一个文档中使用,就需要想想办法,于是 XML 就有了命名空间用于区分含义不同但是名称相同的标签。
它的语法是:
xmlns:命名空间前缀="namespaceURI"
它可以出现在任意标签的开始标签中,用于指定该标签及其所有子标签所使用的命名空间。空间定义好之后,就可以通过在该标签名前添加对应的前缀来使用那个命名空间的标签。
<命名空间前缀:标签名></命名空间前缀:标签名>
例如:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:application.properties" /><util:property-placeholder location="classpath:other.properties" /><bean id="Demo01" class="com.hello.Demo01"></bean>
</beans>
Q:通过观察我们发现,为什么有的命名空间有前缀,例如 **xmlns:util**
,**xmlns:context**
等,而有一个却没有呢?
**A:因为在 XML 中可以指定默认的命名空间,它不需要指定前缀,所有没有前缀的标签都属于默认的命名空间。例如上文中出现的 ****<bean id="Demo01" class="com.hello.Demo01"></bean>**
就属于默认的命名空间,显然默认的命名空间只能有一个。
Q:xmlns 的值(即 URI 字符串)的作用是什么?
A:xmlns 中的 URI 的主要作用是提供命名空间的唯一标识,而不是提供实际的资源或数据。因此,我们通常不会使用 URI 中的内容,而是使用 URI 来标识和引用命名空间,理论上我们可以用任意的字符串来作为命名空间的唯一标识,但在实际应用中,为了确保唯一性和可管理性,建议使用经过规划的、符合相关标准的URI。
总结
XML 是这样一种文档:
- 首先,它是由标签和属性组成,标签总是成对出现,且不能出现交叉(一个标签中包含另一个标签的一部分),属性则是用于描述标签的额外信息。
- XML 没有官方标签,必须由使用者自己去定义,并且赋予其意义
- 不同场景下可能会出现相同的标签,命名空间的出现就是为了区分它们。命名空间由 xmlns:前缀="命名空间URI”组成,理论上 可以使用任意字符串,但是建议使用 URI。
这篇文章不涉及 XML 的解析,只是作为一个快速入门,让你了解 XML 到底是一种什么样的数据结构,在实际的使用中面对其中的元素不至于一脸懵,当我们知道它的具体含义时,使用起来就会更得心应手。如果想要了解更多关于 XML 的相关知识或者是其他技术,可以在我的评论区留言,我将会持续输出更有意思的内容。