关于在序列中在 xsi:type 上使用 xs:unique [英] About using xs:unique on xsi:type in a sequence

查看:33
本文介绍了关于在序列中在 xsi:type 上使用 xs:unique的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以对元素的类型进行唯一约束吗?

It is possible to have a unique constraint on an element's type ?

假设我有一个诺亚方舟,其中 Animal/@name 必须是唯一的.

Let's say I have a Noah's Ark where Animal/@name must be unique.

以下是不针对架构进行验证的 XML:

Below's an XML that do not validate against the schema:

<ns:NoahsArk xmlns:ns="http://www.xxx.com" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.xxx.com Persons.xsd"> 
    <Animal xs:type="ns:Dog" ns:name="Gipsy" ns:pedigree="caniche"/>
    <Animal xs:type="ns:Spider" ns:name="Gipsy" ns:legNumber="5"/>
</ns:NoahsArk>


<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns="http://www.xxx.com"
targetNamespace="http://www.xxx.com" elementFormDefault="unqualified" attributeFormDefault="qualified"> 
    <xs:element name="NoahsArk">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Animal" maxOccurs="unbounded" type="ns:Animal"/>
            </xs:sequence>
        </xs:complexType>
        <xs:unique name="NameUnicity">
            <xs:selector xpath="Animal"/>
            <xs:field xpath="@ns:name"/>
        </xs:unique>
    </xs:element>
    <xs:complexType name="Animal" abstract="true">
        <xs:attribute name="name" type="xs:string" use="required"/>
    </xs:complexType>
    <xs:complexType name="Dog">
        <xs:complexContent>
            <xs:extension base="ns:Animal">
                <xs:attribute name="pedigree" type="xs:string" use="required"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="Spider">
        <xs:complexContent>
            <xs:extension base="ns:Animal">
                <xs:attribute name="legNumber" type="xs:integer" use="required"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>    
</xs:schema>

那很好,但现在假设我想要一个诺亚方舟,其中 Animal/@xsi:type 是独一无二的.

That's good but now let's say I want an Noah's Ark where Animal/@xsi:type are unique.

我尝试了这个约束:

<xs:unique name="AnimalUnicity">
    <xs:selector xpath="Animal"/>
    <xs:field xpath="@xs:type"/>
</xs:unique>

但是这个 XML 仍然有效 :(

But this XML is still valid :(

<?xml version="1.0" encoding="UTF-8"?>
<ns:NoahsArk xmlns:ns="http://www.xxx.com" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.xxx.com Persons.xsd">
    <Animal xs:type="ns:Dog" ns:name="Pierre-Louis" ns:pedigree="doberman"/>
    <Animal xs:type="ns:Spider" ns:name="Gipsy" ns:legNumber="5"/>
</ns:NoahsArk>

有什么想法吗?

谢谢,-E

推荐答案

我可以在 XSD 1.0 上测试的所有实现在这里似乎都同意一件事:身份约束 仅在选择器/字段与关联用户定义架构组件的 XML 节点匹配时才会被测试可以被找寻到.xsi:type,虽然它是与模式相关的标记,但这里不考虑因为目的不同.检查 Schematron 断言是否有帮助可能在学术上很有趣...

All the implementations I could test on XSD 1.0 seem to agree on one thing here: the identity constraints will be tested only if the selectors/fields match XML nodes for which an associated user defined schema component can be found. xsi:type, while it is a schema related markup, is not considered here since its intention is different. It might prove academically interesting to check if a Schematron assertion might help here...

更新:我也包括了 Schematron 版本;因为我在 .NET 上,所以我正在运行 ISO 版本,XSLT1 w/Microsoft 扩展.

UPDATE: I am including the Schematron version, too; I am running the ISO version, XSLT1 w/ Microsoft extensions since I am on .NET.

<?xml version="1.0"?>
<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron" xmlns:ms="urn:schemas-microsoft-com:xslt">
    <sch:ns uri="http://www.w3.org/2001/XMLSchema-instance" prefix="xsi"/>
    <sch:ns uri="urn:schemas-microsoft-com:xslt" prefix="ms"/>

   <sch:pattern id="about-using-xsunique-on-xsitype-in-a-sequence">
      <sch:rule context="//Animal/@xsi:type">
        <sch:let name="targetNodeSet" value="//Animal/@xsi:type"/>
        <sch:assert test="count($targetNodeSet[concat('{', ms:namespace-uri(.), '}', ms:local-name(.)) = concat('{', ms:namespace-uri(current()), '}', ms:local-name(current()))]) = 1">
            Only one-of-a-kind animal is allowed.</sch:assert>
        <sch:assert test="count($targetNodeSet[. = current()]) = 1">
            Only one-of-a-kind animal is allowed (naive).</sch:assert>
      </sch:rule>
   </sch:pattern>
</sch:schema>

我定义了两个断言,一个天真的"断言,它以文本方式比较 xsi:type 属性的值;以及将它们作为 QName 进行比较的正确".

I've defined two assertion, a "naive" one that textually compares the value of the xsi:type attribute; and the "correct" one which compares them as QName s.

对于此 XML:

<ns:NoahsArk xmlns:ns1="http://www.xxx.com" xmlns:ns="http://www.xxx.com" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.xxx.com Persons.xsd">  
    <Animal xs:type="ns:Dog" ns:name="A" ns:pedigree="caniche"/> 
    <Animal xs:type="ns1:Dog" ns:name="B" ns:pedigree="caniche"/> 
    <Animal xs:type="ns1:Dog" ns:name="C" ns:pedigree="caniche"/> 
</ns:NoahsArk> 

结果如下:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<svrl:schematron-output title="" schemaVersion="" xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:schold="http://www.ascc.net/xml/schematron" xmlns:sch="http://www.ascc.net/xml/schematron" xmlns:iso="http://purl.oclc.org/dsdl/schematron" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ms="urn:schemas-microsoft-com:xslt">
    <svrl:ns-prefix-in-attribute-values uri="http://www.w3.org/2001/XMLSchema-instance" prefix="xsi"/>
    <svrl:ns-prefix-in-attribute-values uri="urn:schemas-microsoft-com:xslt" prefix="ms"/>
    <svrl:active-pattern id="about-using-xsunique-on-xsitype-in-a-sequence" name="about-using-xsunique-on-xsitype-in-a-sequence"/>
    <svrl:fired-rule context="//Animal/@xsi:type"/>
    <svrl:failed-assert test="count($targetNodeSet[concat(', ms:namespace-uri(.), ', ms:local-name(.)) = concat(', ms:namespace-uri(current()), ', ms:local-name(current()))]) = 1" location="/@*[local-name()='type' and namespace-uri()='http://www.w3.org/2001/XMLSchema-instance']">
        <svrl:text>
            Only one-of-a-kind animal is allowed.</svrl:text>
    </svrl:failed-assert>
    <svrl:fired-rule context="//Animal/@xsi:type"/>
    <svrl:failed-assert test="count($targetNodeSet[concat(', ms:namespace-uri(.), ', ms:local-name(.)) = concat(', ms:namespace-uri(current()), ', ms:local-name(current()))]) = 1" location="/@*[local-name()='type' and namespace-uri()='http://www.w3.org/2001/XMLSchema-instance']">
        <svrl:text>
            Only one-of-a-kind animal is allowed.</svrl:text>
    </svrl:failed-assert>
    <svrl:failed-assert test="count($targetNodeSet[. = current()]) = 1" location="/@*[local-name()='type' and namespace-uri()='http://www.w3.org/2001/XMLSchema-instance']">
        <svrl:text>
            Only one-of-a-kind animal is allowed (naive).</svrl:text>
    </svrl:failed-assert>
    <svrl:fired-rule context="//Animal/@xsi:type"/>
    <svrl:failed-assert test="count($targetNodeSet[concat(', ms:namespace-uri(.), ', ms:local-name(.)) = concat(', ms:namespace-uri(current()), ', ms:local-name(current()))]) = 1" location="/@*[local-name()='type' and namespace-uri()='http://www.w3.org/2001/XMLSchema-instance']">
        <svrl:text>
            Only one-of-a-kind animal is allowed.</svrl:text>
    </svrl:failed-assert>
    <svrl:failed-assert test="count($targetNodeSet[. = current()]) = 1" location="/@*[local-name()='type' and namespace-uri()='http://www.w3.org/2001/XMLSchema-instance']">
        <svrl:text>
            Only one-of-a-kind animal is allowed (naive).</svrl:text>
    </svrl:failed-assert>
</svrl:schematron-output>

正如您从失败的断言中看到的,天真的"方式仅标记 3 个实例中的 2 个;同样,将 xsi:type 属性的值作为文本进行比较与比较 QName s(这就是 @xsi:types 是什么)不同.

As you can see from the failed assertions, the "naive" way is flagging only 2 of 3 instances; again, comparing the value of the xsi:type attribute as text is not the same as comparing QName s (which is what @xsi:types are).

这篇关于关于在序列中在 xsi:type 上使用 xs:unique的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆