You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python依据XSD文件验证关联的两个XML文件

解决跨XML文档的ID/IDREF关联验证问题

问题分析

你当前的验证方式存在两个核心问题:

  1. XSD约束定义错误:xs:unique和xs:keyref被定义在<review>元素下,而xpath="book"和xpath="review"是相对于<review>元素的路径,无法找到对应的<book>或其他<review>元素,导致约束完全失效。
  2. 单文档验证局限性:默认的XML Schema验证仅针对单个文档,无法检查跨文档的xs:IDREF是否指向另一个文档中存在的xs:ID。

解决方案一:合并XML文档(推荐,符合标准Schema规范)

将两个独立的XML文件合并到一个包含根元素的文档中,同时修正XSD的约束定义,让key/keyref约束作用于整个文档的元素。

1. 修正后的XSD(file.xsd)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <!-- 定义根元素,包含多个book和review -->
  <xs:element name="library">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="book" type="bookType" maxOccurs="unbounded"/>
        <xs:element name="review" type="reviewType" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
    <!-- 定义key:确保所有book的id唯一且存在 -->
    <xs:key name="bookID">
      <xs:selector xpath="book"/>
      <xs:field xpath="@id"/>
    </xs:key>
    <!-- 定义keyref:确保review的ref必须匹配某个book的id -->
    <xs:keyref name="reviewRef" refer="bookID">
      <xs:selector xpath="review"/>
      <xs:field xpath="@ref"/>
    </xs:keyref>
  </xs:element>

  <!-- book类型定义 -->
  <xs:complexType name="bookType">
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="author" type="xs:string"/>
    </xs:sequence>
    <xs:attribute name="id" type="xs:string" use="required"/>
  </xs:complexType>

  <!-- review类型定义 -->
  <xs:complexType name="reviewType">
    <xs:sequence>
      <xs:element name="comment" type="xs:string"/>
      <xs:element name="score" type="xs:integer"/>
    </xs:sequence>
    <xs:attribute name="ref" type="xs:string" use="required"/>
  </xs:complexType>
</xs:schema>

2. 合并后的XML文档(combined.xml)

<library>
  <book id="l1">
    <title>El señor de los anillos</title>
    <author>J.R.R. Tolkien</author>
  </book>
  <review ref="l1">
    <comment>Un clásico de la literatura</comment>
    <score>5</score>
  </review>
</library>

3. 验证代码

from xmlschema import XMLSchema

schema = XMLSchema('file.xsd')
# 验证合并后的文档,此时会自动检查ref是否指向存在的book id
schema.validate('combined.xml')

解决方案二:跨文档验证(保留独立文件)

如果必须保留两个独立的XML文件,可以利用xmlschema库的多文档验证能力,将两个文档加载到同一个验证上下文中,同时调整XSD约束为全局级别。

1. 修正后的XSD(file.xsd)

移除错误的xs:unique和xs:keyref,保留ID/IDREF类型:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="book" type="bookType"/>
  <xs:element name="review" type="reviewType"/>

  <xs:complexType name="bookType">
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="author" type="xs:string"/>
    </xs:sequence>
    <xs:attribute name="id" type="xs:ID" use="required"/>
  </xs:complexType>

  <xs:complexType name="reviewType">
    <xs:sequence>
      <xs:element name="comment" type="xs:string"/>
      <xs:element name="score" type="xs:integer"/>
    </xs:sequence>
    <xs:attribute name="ref" type="xs:IDREF" use="required"/>
  </xs:complexType>
</xs:schema>

2. 跨文档验证代码

使用xmlschema的XMLResource加载两个文档,共享ID池进行验证:

from xmlschema import XMLSchema, XMLResource

schema = XMLSchema('file.xsd')

# 加载第一个文档,获取ID池并验证
book_doc = XMLResource('file1.xml', schema=schema)
book_doc.validate()

# 加载第二个文档,复用第一个文档的ID池进行验证
review_doc = XMLResource('file2.xml', schema=schema, globals=book_doc.globals)
review_doc.validate()

这种方式会让第二个文档的xs:IDREF检查第一个文档中的xs:ID是否存在,如果ref指向不存在的ID,会抛出验证错误。


内容的提问来源于stack exchange,提问作者Usuario86

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:15:48