可以对元素的类型设置唯一约束吗?
假设我有一个Noah方舟,其中Animal / @ name必须是唯一的。
下面是一个不针对架构验证的XML:
<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是唯一的。
我试过这个约束:
<xs:unique name="AnimalUnicity">
<xs:selector xpath="Animal"/>
<xs:field xpath="@xs:type"/>
</xs:unique>
但是这个XML仍然有效:(
<?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
答案 0 :(得分:0)
我可以在XSD 1.0上测试的所有实现似乎都在这里达成一致:仅当选择器/字段匹配关联的用户定义的的XML节点时才会测试identity constraints >可以找到架构组件。 xsi:type虽然它是与模式相关的标记,但由于其意图不同,因此不在此考虑。检查Schematron断言是否可能对此有所帮助可能在学术上很有趣......
更新:我也包括Schematron版本;我正在运行ISO版本,XSLT1带有Microsoft扩展,因为我在.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 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是什么)不同。
答案 1 :(得分:0)
感谢您的回复。
为了好玩,我尝试了Schematron;但是我无法使它工作,因为我发现XPath表达式使用“current()”,这在氧气或XMLSpy中不可用,所以我无法测试它:(
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.ascc.net/xml/schematron" xmlns:ns="http://www.xxx.com" >
<ns prefix="ns" uri="http://www.xxx.com"/>
<ns prefix="xs" uri="http://www.w3.org/2001/XMLSchema-instance"/>
<pattern name="AnimalNameUnicity">
<rule context="Animals/Animal">
<assert test="count(//@ns:name[ . = current()]) > 1">name not unique !</assert>
</rule>
</pattern>
</schema>