XML文档中经常会包含各种相对URI,比如引用的外部资源路径、链接地址等,这些相对URI的解析基准默认是文档本身的位置,而xml:base属性可以修改这个基准,从而改变相对URI的最终解析结果。xml:base是XML规范中定义的一个标准属性,属于XML命名空间下的属性,用于指定当前元素及其子元素的基准URI。

xml:base属性的基本设置规则
xml:base属性可以出现在XML文档的任意元素上,属性值需要是一个绝对URI或者相对URI。当设置在某个元素上时,该元素及其所有子元素内的相对URI都会以这个属性指定的值为基准进行解析,除非子元素本身也设置了xml:base属性覆盖父级的设置。
下面是一个简单的XML示例,展示xml:base的基本用法:
<?xml version="1.0" encoding="UTF-8"?>
<root xml:base="https://ipipp.com/resources/">
<item>
<link>styles/main.css</link>
</item>
</root>
在这个示例中,root元素设置了xml:base为https://ipipp.com/resources/,那么item元素下的link里的相对URIstyles/main.css会被解析为https://ipipp.com/resources/styles/main.css。
xml:base对相对URI解析的具体影响
基准URI的替换逻辑
相对URI的解析遵循RFC 3986中定义的规则,xml:base的作用就是将默认的基准URI替换为自身指定的URI。如果xml:base的值是相对URI,那么它会先基于之前的基准URI解析为绝对URI,再作为新的基准。
看下面的示例:
<?xml version="1.0" encoding="UTF-8"?>
<root xml:base="https://ipipp.com/a/">
<level1 xml:base="b/">
<level2>
<uri>test.xml</uri>
</level2>
</level1>
</root>
这里的解析过程是:root的基准是https://ipipp.com/a/,level1的xml:base是相对URIb/,先基于root的基准解析为https://ipipp.com/a/b/,所以level2下的test.xml最终解析为https://ipipp.com/a/b/test.xml。
不同相对URI类型的处理
相对URI分为多种类型,比如相对路径、绝对路径、带查询参数的相对URI等,xml:base对这些类型的处理都遵循统一的基准替换规则:
- 以
./开头的相对URI:直接拼接在基准URI之后 - 以
../开头的相对URI:先基于基准URI向上回退对应层级再拼接 - 以
/开头的相对URI:替换基准URI的路径部分,保留协议、域名等部分
下面是一个不同相对URI类型的解析示例:
<?xml version="1.0" encoding="UTF-8"?>
<root xml:base="https://ipipp.com/api/v1/">
<case1>./user/list</case1>
<case2>../config.json</case2>
<case3>/static/js/app.js</case3>
</root>
对应的解析结果分别是:
- case1:
https://ipipp.com/api/v1/user/list - case2:
https://ipipp.com/api/config.json - case3:
https://ipipp.com/static/js/app.js
xml:base的继承与覆盖规则
xml:base属性具有继承性,子元素会默认继承父元素的xml:base值,除非子元素显式设置了xml:base属性。如果子元素的xml:base是绝对URI,那么会直接替换父级的基准,不再基于父级基准解析。
下面的示例展示了继承与覆盖的效果:
<?xml version="1.0" encoding="UTF-8"?>
<root xml:base="https://ipipp.com/base/">
<parent>
<child1>page1.html</child1>
<child2 xml:base="https://ipipp.com/new/">page2.html</child2>
<child3 xml:base="sub/">page3.html</child3>
</parent>
</root>
三个child元素的解析结果分别是:
- child1:继承parent的基准
https://ipipp.com/base/,结果为https://ipipp.com/base/page1.html - child2:使用绝对URI作为基准,结果为
https://ipipp.com/new/page2.html - child3:相对URI基于parent的基准解析,新基准为
https://ipipp.com/base/sub/,结果为https://ipipp.com/base/sub/page3.html
实际开发中的注意事项
在使用xml:base属性时,需要注意以下几点:
- xml:base属性属于
http://www.w3.org/XML/1998/namespace命名空间,虽然大部分XML解析器会默认识别,但最好显式声明该命名空间避免解析错误 - 不要在xml:base值中包含特殊字符,如果有需要要进行URI编码
- XML解析器对xml:base的支持程度可能不同,在跨平台使用时需要测试解析结果是否符合预期
下面是一个带命名空间声明的规范示例:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xml="http://www.w3.org/XML/1998/namespace" xml:base="https://ipipp.com/data/">
<item>info.json</item>
</root>