XML 编码(超详细)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

XML 的基本结构与语法

XML(eXtensible Markup Language)是一种可扩展标记语言,它通过自定义标签来描述数据的结构和内容。对于编程初学者而言,可以将 XML 比作一个“数据目录”,每个标签就像文件夹,用来分类和组织信息。例如,一个电商订单的 XML 结构可能如下:

<Order id="1001">
    <Customer name="张三" email="zhangsan@example.com"/>
    <Product name="笔记本电脑" price="999.99"/>
    <ShippingAddress country="中国" city="北京"/>
</Order>

这段代码中,<Order> 是根元素,包含子元素 <Customer><Product><ShippingAddress>。每个元素通过标签名和属性描述数据,这种结构化设计使得 XML 成为跨平台数据交换的理想选择。

元素与标签的规则

XML 的元素由开始标签、结束标签和中间内容组成,例如:

<Book title="深入理解 XML">
    <Author>李四</Author>
    <Publisher>技术出版社</Publisher>
</Book>  

这里 <Book> 是开始标签,</Book> 是结束标签,中间的内容描述了书籍的作者和出版社。需要注意以下规则:

  • 标签必须正确闭合,空元素需使用自闭合标签(如 <Customer/>)。
  • 标签名区分大小写,<Customer><customer> 被视为不同元素。
  • 文本内容需严格符合 XML 语法,特殊字符(如 <>)需转义。

属性与元素的对比

XML 中的属性和元素都能描述数据,但二者用途不同:

  • 属性:适合描述元素的附加信息,如 <Product price="99.99"/>
  • 元素:适合描述独立的数据块,如 <Description>...</Description>

选择属性还是元素,取决于数据的复杂性。例如,用户地址可能更适合用元素:

<Customer>
    <Name>王五</Name>
    <Address>
        <Street>中山路1号</Street>
        <City>上海</City>
    </Address>
</Customer>  

文档类型定义(DTD)与 Schema

XML 的灵活性需要约束机制,以确保数据符合预期格式。通过 DTD 或 XML Schema 可以定义元素、属性的规则。例如,DTD 可以规定 <Order> 元素必须包含 <Customer><Product>

<!-- DTD 示例 -->
<!ELEMENT Order (Customer, Product, ShippingAddress)>
<!ELEMENT Customer (#PCDATA)>
<!ELEMENT Product (#PCDATA)>

而 XML Schema(XSD)则提供更强大的类型定义:

<xsd:element name="Price" type="xsd:decimal"/>

编码细节:字符集与特殊符号

XML 的编码问题直接影响数据的兼容性和可读性。以下是关键点:

  1. 字符编码:默认使用 UTF-8,需在文档开头声明:
    <?xml version="1.0" encoding="UTF-8"?>  
    
  2. 特殊字符转义
    • <&lt;
    • >&gt;
    • &&amp;

例如,若内容包含 HTML 标签,需转义处理:

<Content>这是一个测试,内容包含 &lt;b&gt;加粗&lt;/b&gt; 文字。</Content>  

XML 编码的实践:生成与解析

掌握 XML 编码后,需通过编程语言实现数据的生成和解析。以下以 Python 和 Java 为例,展示常见操作。

Python 中的 XML 处理

Python 提供 xml.etree.ElementTree 模块,支持创建和解析 XML。例如,生成一个订单的 XML 文件:

import xml.etree.ElementTree as ET  

order = ET.Element("Order", attrib={"id": "1001"})  

customer = ET.SubElement(order, "Customer",  
                        attrib={"name": "张三", "email": "zhangsan@example.com"})  
product = ET.SubElement(order, "Product", attrib={"price": "999.99"})  

tree = ET.ElementTree(order)  
ET.indent(tree, space="    ")  # 自动缩进  
tree.write("order.xml", encoding="utf-8", xml_declaration=True)  

解析 XML 的代码示例:

tree = ET.parse("order.xml")  
root = tree.getroot()  

for child in root:  
    print(child.tag, child.attrib)  

Java 中的 DOM 解析器

Java 使用 DOM(Document Object Model)或 SAX(Simple API for XML)解析 XML。DOM 将整个文档加载到内存,适合中小型数据。以下代码演示如何解析订单信息:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
DocumentBuilder builder = factory.newDocumentBuilder();  
Document doc = builder.parse("order.xml");  

NodeList orderList = doc.getElementsByTagName("Order");  
for (int i = 0; i < orderList.getLength(); i++) {  
    Node orderNode = orderList.item(i);  
    if (orderNode.getNodeType() == Node.ELEMENT_NODE) {  
        Element orderElement = (Element) orderNode;  
        String customerId = orderElement.getAttribute("id");  
        System.out.println("订单 ID: " + customerId);  
    }  
}  

生成与解析的对比

  • 生成:需按层级构建元素,注意属性的添加顺序和标签闭合。
  • 解析:需处理异常(如文件不存在)、遍历节点(如 getElementsByTagName)以及类型转换(如将字符串转为数字)。

进阶技巧:命名空间与 XPath

XML 命名空间(Namespace)

当多个 XML 文档共享相同标签名时,命名空间可避免冲突。例如,两个供应商的 <Product> 标签可通过命名空间区分:

<Products xmlns:vendorA="http://vendorA.com"  
          xmlns:vendorB="http://vendorB.com">  
    <vendorA:Product id="P001">...</vendorA:Product>  
    <vendorB:Product id="P002">...</vendorB:Product>  
</Products>  

XPath 查询语言

XPath 是用于在 XML 文档中定位节点的表达式语言。例如,查询订单的客户名称:

//Order/Customer/@name  

在 Python 中使用 lxml 库执行 XPath:

from lxml import etree  

tree = etree.parse("order.xml")  
result = tree.xpath("//Order/Customer/@name")  
print(result[0].value)  # 输出:"张三"  

常见问题与解决方案

问题 1:XML 编码错误

现象:解析时提示“Invalid byte 2 of 3-byte UTF-8 sequence”。
原因:文件实际编码与声明不符(如声明 UTF-8,但文件保存为 GBK)。
解决方案

  1. 确保编辑器保存时选择 UTF-8 编码。
  2. 检查特殊字符是否已转义。

问题 2:元素嵌套错误

现象:XML 验证失败,提示“Element 'Order' has extra content: Customer”。
原因:DTD 或 Schema 定义的结构与实际 XML 不匹配。
解决方案

  1. 检查 DTD 中的元素顺序和嵌套关系。
  2. 使用 XML 验证工具(如 Oxygen XML Editor)高亮错误位置。

问题 3:命名空间未声明

现象:XPath 查询返回空结果。
原因:未在代码中注册命名空间前缀。
解决方案(以 Python 的 lxml 为例):

ns = {"vendorA": "http://vendorA.com"}  
result = tree.xpath("//vendorA:Product", namespaces=ns)  

结论

XML 编码是编程中不可或缺的技能,尤其在数据交换、配置管理等领域具有广泛应用。通过本文的学习,读者应能:

  1. 理解 XML 的基本结构与语法规则。
  2. 掌握生成和解析 XML 的编程实践。
  3. 运用命名空间和 XPath 解决复杂场景下的数据处理问题。

对于初学者,建议从简单案例入手,逐步扩展到 DTD 设计和多命名空间场景。随着实践加深,XML 编码将成为连接不同系统、规范数据格式的重要工具。未来可进一步探索 XML 与 JSON 的对比、SOAP 等 Web 服务协议中的 XML 应用,以拓宽技术视野。

最新发布