1

要素の型に一意の制約を設定することは可能ですか?

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

4

2 に答える 2

0

Thanks for your response.

Just for fun I made an attempt with Schematron ; however I couldn't make it work since the XPath expression I find out uses "current()" which is not available in oxygen or XMLSpy, so I can't test it :(

    <?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>
于 2012-10-10T12:21:02.580 に答える
0

XSD 1.0 でテストできたすべての実装は、ここで 1 つのことに同意しているようです。ID制約は、セレクター/フィールドが、関連するユーザー定義のスキーマ コンポーネントが見つかるXML ノードと一致する場合にのみテストされます。xsi:typeはスキーマ関連のマークアップですが、意図が異なるため、ここでは考慮しません。ここでSchematronのアサーションが役立つかどうかを確認することは、学術的に興味深いかもしれません...

更新: Schematron バージョンも含めます。私は .NET を使用しているため、Microsoft 拡張機能を備えた ISO バージョン XSLT1 を実行しています。

<?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>

2 つのアサーションを定義しました。1 つは xsi:type 属性の値をテキストで比較する「単純な」アサーションです。そしてそれらをQNameとして比較する「正しい」もの。

この 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を比較することと同じではありません(@xsi:types とは)。

于 2012-10-09T16:01:38.013 に答える