可以使用lxml
来针对给定的XSD架构验证XML文件。
有没有办法在严格意义上应用此验证,忽略包含特殊表达式的所有元素?
请考虑以下示例:说,我有一个 xml_file :
<foo>99</foo>
<foo>{{var1}}</foo>
<foo>{{var2}}</foo>
<foo>999</foo>
现在,我在这个文件上运行一个程序,它取代{{...}}
- 表达式并生成一个新文件:
xml_file_new :
<foo>99</foo>
<foo>23</foo>
<foo>42</foo>
<foo>999</foo>
到目前为止,我可以使用lxml
来验证新的XML文件,如下所示:
from lxml import etree
xml_root = etree.parse(xml_file_new)
xsd_root = etree.parse(xsd_file)
schema = etree.XMLSchema(xsd_root)
schema.validate(xml_root)
我的示例中的相关点是架构将<foo>
内容限制为整数。
不可能提前在旧的xml_file
上应用架构,但是,由于我的程序执行了一些其他昂贵的任务,我希望在忽略包含任何{{1 }} - 表达式:
{{...}}
编辑:可能的解决方案方法:一个想法是定义两个架构
<foo>99</foo> <!-- should be checked-->
<foo>{{var1}}</foo> <!-- should be ignored -->
<foo>{{var2}}</foo> <!-- should be ignored -->
<foo>999</foo> <!-- should be checked-->
- 表达式但是,为了避免保持两个模式同步的冗余任务,需要一种方法来自动从严格模式生成松弛。这听起来很有希望,因为两个模式具有相同的结构,只是在某些元素内容的限制方面有所不同。是否有一个简单的概念由XSD提供,它允许从一个模式“继承”,然后“附加”额外的松弛到个别元素?
答案 0 :(得分:1)
要回答编辑过的问题,可以使用xs:inlcude
(和xs:import
)机制组合模式。这样,您可以在公共模式中声明公共部分以供重用,并使用专用模式进行专门的类型定义,如下所示:
描述结构的通用架构。
请注意,它使用FooType
,但未定义它:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- Example structure -->
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="foo" type="FooType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
要在替换之前验证的宽松架构。
它包括来自通用模式的组件,
并定义了一个轻松的FooType
:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="common.xsd"/>
<xs:simpleType name="FooType">
<xs:union memberTypes="xs:integer">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="\{\{.*\}\}"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:schema>
替换后验证的严格架构。它
定义FooType
的严格版本:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="common.xsd"/>
<xs:simpleType name="FooType">
<xs:restriction base="xs:integer"/>
</xs:simpleType>
</xs:schema>
为了完成,还有其他方法可以做到这一点,
例如xs:redefine
(XSD 1.0)或xs:override
(XSD 1.1)。
但是这些语义更复杂,而且我个人试图避免它们。
答案 1 :(得分:0)
只是简单的XSD,我不知道有什么办法可以避免 整数类型的冗余声明。然而, 作为替代方案,您可以在Python中调整架构。
一种简单的方法是,只使用一个模式文档(默认情况下放宽):
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="foo" type="FooType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="FooType">
<xs:union memberTypes="xs:integer">
<xs:simpleType id="RELAXED">
<xs:restriction base="xs:string">
<xs:pattern value="\{\{.*\}\}"/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:schema>
在Python中,您只需使用id="RELAXED"
删除元素即可创建严格架构:
from lxml import etree
xsd_tree = etree.parse("relaxed.xsd")
xml_tree = etree.parse("test.xml")
# Create default relaxed schema
relaxed_schema = etree.XMLSchema(xsd_tree)
# Remove RELAXED element to create strict schema
pattern = xsd_tree.find(".//*[@id='RELAXED']")
pattern.getparent().remove(pattern)
strict_schema = etree.XMLSchema(xsd_tree)
print("Relaxed:", relaxed_schema.validate(xml_tree))
print("Strict:", strict_schema.validate(xml_tree))
当然,使用Python,您可以通过多种方式实现此目的。例如,您还可以动态生成xs:union
元素并将其插入严格版本的模式中。但这会变得更加复杂。