XML 文档的有效性(Validity)和格式良好性(Well-formedness)是两个重要的概念,它们定义了 XML 文档的质量标准。
格式良好(Well-formed)
格式良好是指 XML 文档符合 XML 语法规则,可以被 XML 解析器正确解析。
格式良好的要求
-
必须有单一的根元素
xml<!-- 正确:有单一根元素 --> <root> <child>内容</child> </root> <!-- 错误:没有单一根元素 --> <child1>内容</child1> <child2>内容</child2> -
所有标签必须正确关闭
xml<!-- 正确:所有标签都关闭 --> <root> <child>内容</child> </root> <!-- 错误:标签未关闭 --> <root> <child>内容 </root> -
标签必须正确嵌套
xml<!-- 正确:正确嵌套 --> <root> <parent> <child>内容</child> </parent> </root> <!-- 错误:错误嵌套 --> <root> <parent> <child>内容 </parent> </child> </root> -
属性值必须用引号括起来
xml<!-- 正确:属性值用引号括起来 --> <book id="1" category="web">内容</book> <!-- 错误:属性值未用引号括起来 --> <book id=1 category=web>内容</book> -
标签名称区分大小写
xml<!-- 正确:大小写一致 --> <root> <Child>内容</Child> </root> <!-- 错误:大小写不一致 --> <root> <child>内容</Child> </root> -
特殊字符必须转义
xml<!-- 正确:特殊字符已转义 --> <data>5 < 10 & 20 > 15</data> <!-- 错误:特殊字符未转义 --> <data>5 < 10 & 20 > 15</data> -
空元素必须正确表示
xml<!-- 正确:空元素表示方式 --> <empty/> <empty></empty> <!-- 错误:空元素表示不正确 --> <empty>
有效(Valid)
有效是指 XML 文档不仅格式良好,还符合特定的文档类型定义(DTD)或 XML Schema。
有效的要求
-
必须格式良好
- 有效的文档首先必须是格式良好的
-
必须符合 DTD 或 Schema
xml<!-- XML 文档 --> <?xml version="1.0"?> <!DOCTYPE note SYSTEM "note.dtd"> <note> <to>John</to> <from>Jane</from> <heading>Reminder</heading> <body>Don't forget the meeting!</body> </note> <!-- DTD 文件 (note.dtd) --> <!ELEMENT note (to, from, heading, body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)> -
元素和属性必须符合定义
xml<!-- XML Schema --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="book"> <xs:complexType> <xs:sequence> <xs:element name="title" type="xs:string"/> <xs:element name="author" type="xs:string"/> <xs:element name="price" type="xs:decimal"/> </xs:sequence> <xs:attribute name="id" type="xs:string" use="required"/> </xs:complexType> </xs:element> </xs:schema> <!-- 有效的 XML 文档 --> <book id="1"> <title>XML Guide</title> <author>John Doe</author> <price>39.95</price> </book> <!-- 无效的 XML 文档(缺少必需的属性) --> <book> <title>XML Guide</title> <author>John Doe</author> <price>39.95</price> </book> -
数据类型必须匹配
xml<!-- 正确:数据类型匹配 --> <price>39.95</price> <!-- 错误:数据类型不匹配 --> <price>thirty-nine point ninety-five</price>
格式良好 vs 有效的对比
| 特性 | 格式良好 | 有效 |
|---|---|---|
| 语法要求 | 必须符合 XML 语法规则 | 必须符合 XML 语法规则 |
| 结构要求 | 必须有单一根元素 | 必须有单一根元素 |
| 验证要求 | 不需要 DTD 或 Schema | 需要 DTD 或 Schema |
| 约束检查 | 不检查约束 | 检查所有约束 |
| 数据类型 | 不检查数据类型 | 检查数据类型 |
| 必需元素 | 不检查必需元素 | 检查必需元素 |
| 属性约束 | 不检查属性约束 | 检查属性约束 |
验证 XML 文档
1. 验证格式良好性
Java 示例:
javaimport javax.xml.parsers.*; import org.xml.sax.*; import org.w3c.dom.*; public class XMLValidator { public static boolean isWellFormed(String xml) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new InputSource(new StringReader(xml))); return true; } catch (Exception e) { System.err.println("XML is not well-formed: " + e.getMessage()); return false; } } }
2. 验证有效性
使用 DTD 验证:
javapublic class XMLValidator { public static boolean isValidWithDTD(String xml, String dtd) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(true); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setErrorHandler(new ErrorHandler() { public void warning(SAXParseException e) { System.err.println("Warning: " + e.getMessage()); } public void error(SAXParseException e) { System.err.println("Error: " + e.getMessage()); } public void fatalError(SAXParseException e) { System.err.println("Fatal Error: " + e.getMessage()); } }); Document document = builder.parse(new InputSource(new StringReader(xml))); return true; } catch (Exception e) { System.err.println("XML is not valid: " + e.getMessage()); return false; } } }
使用 Schema 验证:
javapublic class XMLValidator { public static boolean isValidWithSchema(String xml, String schemaPath) { try { SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = factory.newSchema(new File(schemaPath)); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setSchema(schema); DocumentBuilder builder = docFactory.newDocumentBuilder(); builder.setErrorHandler(new ErrorHandler() { public void warning(SAXParseException e) { System.err.println("Warning: " + e.getMessage()); } public void error(SAXParseException e) { System.err.println("Error: " + e.getMessage()); } public void fatalError(SAXParseException e) { System.err.println("Fatal Error: " + e.getMessage()); } }); Document document = builder.parse(new InputSource(new StringReader(xml))); return true; } catch (Exception e) { System.err.println("XML is not valid: " + e.getMessage()); return false; } } }
最佳实践
- 始终确保格式良好:格式良好是 XML 文档的基本要求
- 使用 Schema 验证:Schema 比 DTD 更强大、更灵活
- 开发时启用验证:在开发阶段启用验证,生产环境可根据需求调整
- 处理验证错误:提供清晰的错误信息,帮助调试
- 使用标准工具:使用成熟的 XML 解析器和验证工具
- 文档化约束:清楚地文档化数据结构和约束
- 版本控制:对 Schema 和 DTD 进行版本控制
格式良好和有效性是 XML 文档质量的两个重要维度。格式良好确保文档可以被解析,而有效性确保文档符合业务规则和数据结构要求。在实际应用中,应该根据需求选择适当的验证级别。