【问题标题】:How do you write an <xs:unique> constraint correctly and/or get lxml to throw an exception when such a constraint is violated? [duplicate]如何正确编写 <xs:unique> 约束和/或在违反此类约束时让 lxml 抛出异常? [复制]
【发布时间】:2014-12-25 22:48:42
【问题描述】:

我试图弄清楚&lt;xs:unique&gt; 约束是如何工作的,作为其中的一部分,我认为是否可以创建一些违反其关联架构中的&lt;xs:unique&gt; 约束的XML 是值得的。所以我在schema.xml 中有这个架构:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="parent">
        <xs:complexType>
            <xs:sequence maxOccurs="unbounded">

                <xs:element name="child">
                    <xs:complexType>
                        <xs:attribute name="foo" type="xs:string" />
                    </xs:complexType>
                    <xs:unique name="someUniqueConstraint">
                        <xs:selector xpath="child" />
                        <xs:field xpath="@foo" />
                    </xs:unique>
                </xs:element>

            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

还有这个文件在data.xml:

<parent>
    <child foo="1" />
    <child foo="2" />
    <child foo="2" />
</parent>

我正在使用 Python 的 lxml 库进行验证,它是 libxml2 的绑定:

from lxml import etree

# load and parse schema and xml
with open('schema.xml', 'r') as f:
    schema_root = etree.parse(f)
with open('data.xml', 'r') as f:
    data_root = etree.parse(f)

schema = etree.XMLSchema(schema_root)
schema.assertValid(data_root)

我的期望是上面的验证代码应该在schema.assertValid 行上引发异常,因为违反了&lt;child&gt; 标签的foo 属性的唯一性约束。但是,这不会发生 - 断言成功。

我猜是 1.) 我写错了 &lt;xs:unique&gt; 约束;或 2.) lxml 和/或 libxml2 实际上并不进行唯一性验证。无论哪种方式,我应该做些什么不同的事情来让lxml 强制执行唯一性约束,以便它将上面的文档视为有效?

(我已经设法从各种其他模式违规中消除了 lxml 的验证错误,所以并不是我安装的 lxml 被破坏或其他原因。)

【问题讨论】:

    标签: python xml xsd lxml


    【解决方案1】:

    看起来我只是在错误的地方设置了 &lt;xs:unique&gt; 约束。

    应该是:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
        <xs:element name="parent">
            <xs:complexType>
                <xs:sequence maxOccurs="unbounded">
    
                    <xs:element name="child">
                        <xs:complexType>
                            <xs:attribute name="foo" type="xs:string" />
                        </xs:complexType>
                    </xs:element>
    
                </xs:sequence>
            </xs:complexType>
    
            <xs:unique name="someUniqueConstraint">
                <xs:selector xpath="child" />
                <xs:field xpath="@foo" />
            </xs:unique>
    
        </xs:element>
    
    </xs:schema>
    

    即约束移动到父元素而不是子元素。我想这是有道理的,因为根据https://stackoverflow.com/a/8806512/1535629(我将作为副本投票关闭),重点是在父母的所有孩子之间强制唯一性,所以我们应该放置父级别的约束,以便它“知道”需要强制执行哪些约束。通过对schema.xml 的更改,验证器确实会引发错误:

    lxml.etree.DocumentInvalid: 元素 'child': Duplicate key-sequence ['2'] in unique identity-constraint 'someUniqueConstraint'., line 4

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 2019-02-04
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多