CodeGym /课程 /JAVA 25 SELF /XML 与命名空间基础

XML 与命名空间基础

JAVA 25 SELF
第 47 级 , 课程 0
可用

1. 认识 XML

尽管今天 JSON 已是标准,在 Java 世界里仍有大量遗留代码,因此你有时仍会遇到 XML。了解它很有用。 XML(eXtensible Markup Language,可扩展标记语言)是一种用于存储与交换结构化数据的文本格式。它常用于配置、程序间交换、数据存储,甚至用于对象序列化。

XML 文档结构的基本要素:

标签(元素):
位于 <> 之间的内容。每个标签都有开始(<tag>)与结束(</tag>),或为自闭合(<tag/>)。

属性:
标签内部的附加参数。
示例: <user name="瓦夏" age="25"/>

文本节点:
位于标签之间的文本。
示例:<greeting>你好,世界!</greeting>

简单 XML 文档示例

<?xml version="1.0" encoding="UTF-8"?>
<users>
    <user name="瓦夏" age="25">你好!</user>
    <user name="卡佳" age="30"/>
</users>

这里:

  • <users> — 根元素。
  • <user> — 带有 nameage 属性的元素,第一个用户还有文本内容。

2. 关键概念

序言(prolog):
文件开头的一行用于指明 XML 版本与编码。
示例: <?xml version="1.0" encoding="UTF-8"?>

元素:
XML 的基本构建块。
示例:<book>...</book>

属性:
位于开始标签中的参数。
示例: <book title="Java" author="伊万诺夫"/>

注释:
与 HTML 类似,写在 <!-- ... --> 之间。
示例:<!-- 这是注释 -->

CDATA 段:
允许插入不会被当作 XML 解析的文本(例如包含 <& 等符号)。
示例:

<script><![CDATA[
    if (a < b && b > 0) { ... }
]]></script>

3. 为什么在 XML 中需要命名空间(namespaces)

问题:名称冲突

在大型 XML 文档中,常会出现名称相同但含义不同的标签。例如,你可能同时有用于 HTML 的 <table>,以及你业务逻辑(例如数据库)中的 <table>。如何区分它们的含义?

没有命名空间:

<root>
    <table>
        <row>...</row>
    </table>
    <table>
        <column>...</column>
    </table>
</root>

这里无法明确每个 <table> 的含义。

解决方案:命名空间

命名空间(namespace)是一种“标记”元素与属性的方式,用来避免名称冲突,并清晰地区分不同标签的语义。

  • 每个命名空间都是唯一的 URI(通常看起来像链接,但它只是一个标识符)。
  • 即使名称相同,属于不同命名空间的元素与属性也被视为不同。

优点:

  • 不同标准与模式之间不会发生名称冲突。
  • 可以在同一文档中合并来自不同来源的数据。
  • 每个标签属于哪个“词汇表”一目了然。

4. 使用命名空间:声明与应用

如何声明命名空间

在某个元素的开始标签中使用特殊属性 xmlns(XML Namespace):

  • 无前缀:xmlns="URI" —— 为所有嵌套元素声明默认命名空间。
  • 带前缀:xmlns:prefix="URI" —— 用前缀(短名)声明命名空间,以便在标签中使用。

声明与使用命名空间的示例

<root xmlns:h="http://www.w3.org/TR/html4/"
      xmlns:f="http://www.w3schools.com/furniture">
    <h:table>
        <h:tr>
            <h:td>单元格 1</h:td>
            <h:td>单元格 2</h:td>
        </h:tr>
    </h:table>
    <f:table>
        <f:name>桌子</f:name>
        <f:width>80</f:width>
        <f:length>120</f:length>
    </f:table>
</root>

这里:

  • xmlns:h="..." —— 为 HTML 表格声明前缀 h
  • xmlns:f="..." —— 为“家具”声明前缀 f
  • <h:table><f:table> —— 即使名称相同,也是不同的元素。

如何使用命名空间

  • 声明: 在根元素或任何元素上:xmlns:prefix="URI"
  • 应用: 在元素或属性名称前加前缀与冒号:<prefix:element>...</prefix:element>

默认命名空间

如果仅声明 xmlns="URI",则所有不带前缀的元素都属于该命名空间。

<books xmlns="http://example.com/books">
    <book>...</book>
</books>

5. 实战:创建一个包含多个命名空间的简单 XML 文档

我们来创建一个示例 XML 文档,其中使用两个命名空间:一个用于 HTML,一个用于“家具”。

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:h="http://www.w3.org/TR/html4/"
      xmlns:f="http://www.w3schools.com/furniture">
    <h:table>
        <h:tr>
            <h:td>单元格 1</h:td>
            <h:td>单元格 2</h:td>
        </h:tr>
    </h:table>
    <f:table>
        <f:name>桌子</f:name>
        <f:width>80</f:width>
        <f:length>120</f:length>
    </f:table>
</root>

这里发生了什么:

  • 在根元素上声明了两个命名空间:hf
  • 所有带前缀 h: 的元素属于 HTML 表格。
  • 所有带前缀 f: 的元素属于“家具”。

6. 常见错误

错误 1:忘记声明前缀

<root>
    <h:table>...</h:table>
</root>

结果: XML 解析器会报错:The prefix 'h' for element 'h:table' is not bound.

错误 2:未使用命名空间的同名元素

<root>
    <table>...</table>
    <table>...</table>
</root>

结果: 无法区分哪个 <table> 属于什么。

错误 3:错误使用前缀

<root xmlns:h="http://www.w3.org/TR/html4/">
    <h:table>...</h:table>
    <f:table>...</f:table> <!-- 错误:未声明前缀 f -->
</root>

结果: 解析器错误:The prefix 'f' for element 'f:table' is not bound.

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION