1

次のXMLを適用するXMLスキーマを実装しようとしています。

<databases>
    <database>
        <name>"Test A"</name>
        <host>"192.168.0.100"</host>
        <default>yes</default>
    </database>
    <database>
        <name>"Test B"</name>
        <host>"192.168.0.200"</host>
        <default>no</default>        
    </database>
    <database>
        <name>"Test C"</name>
        <host>"localhost"</host>
        <default>no</default>        
    </database>
</databases>

1つの重要な問題を除いて、自分でXMLスキーマを実装できます。つまり、最大で1つのデータベースのみをデフォルトとしてマークする必要があります。これは、ゼロデータベースをデフォルトとしてマークできることを意味し、これも有効と見なす必要があります。

例として、複数のデータベースがデフォルトとしてマークされているため、次のXMLはXMLスキーマによって無効と見なされる必要があります。

<databases>
    <database>
        <name>"Test A"</name>
        <host>"192.168.0.100"</host>
        <default>yes</default>
    </database>
    <database>
        <name>"Test B"</name>
        <host>"192.168.0.200"</host>
        <default>no</default>        
    </database>
    <database>
        <name>"Test C"</name>
        <host>"localhost"</host>
        <default>yes</default>        
    </database>

次のXMLは、デフォルトとしてマークされている(ゼロの)データベースがないため、XMLスキーマによって有効であると見なされる必要があります。

<databases>
    <database>
        <name>"Test A"</name>
        <host>"192.168.0.100"</host>
        <default>no</default>
    </database>
    <database>
        <name>"Test B"</name>
        <host>"192.168.0.200"</host>
        <default>no</default>        
    </database>
    <database>
        <name>"Test C"</name>
        <host>"localhost"</host>
        <default>no</default>        
    </database>

XMLスキーマでそのような制約を強制することが可能かどうか誰かが知っていますか?あるべきだと思いますが、どうやって実装すればいいのかわかりません。

この件に関してご協力いただければ幸いです。

前もって感謝します。

4

1 に答える 1

1

1つのデータベースのみがデフォルトとしてマークされていることを確認する最も簡単な方法は、おそらくXMLの構造を変えることです。上記のようにデータベースを記録しますが、要素を削除し、デフォルトデータベースを識別するdefault要素に属性または子要素を追加します。databasesXMLは次のようになります。

<databases default="Test A">
    <database>
        <name>Test A</name>
        <host>"192.168.0.100"</host>
   </database>
    <database>
        <name>Test B</name>
        <host>"192.168.0.200"</host>
   </database>
    <database>
        <name>Test C</name>
        <host>"localhost"</host>
   </database>
</databases>

(実際にはデータベース名の一部ではないという理論に基づいて、要素に引用符を削除しました。名前の一部である場合、デフォルトの属性は引用符を含めてのnameようにする必要があります。)default='"Test A"'

database/name要素が一意であることを確認する必要があります。これは、要素xs:keyの宣言のdatabases構成要素を使用して行います。defaultまた、オプションの属性がデータベース名を指していることを確認する必要があります。でこれを行いxs:keyrefます。の宣言は次のdatabasesようになります。

<xs:element name="databases" type="databases">
  <xs:key name="dbname">
    <xs:selector xpath="database"/>
    <xs:field xpath="name"/>
  </xs:key>
  <xs:keyref refer="dbname" name="defaultdb">
    <xs:selector xpath="."/>
    <xs:field xpath="@default"/>
  </xs:keyref>
</xs:element>

2番目のアプローチでは、を少し不正に使用しますがxs:unique、XMLをリファクタリングする必要があります。databaseの3番目の子をdefaultvaluesyesまたは、で作成する代わりに、3番目の子を名前付き要素またはno名前付き要素のいずれかにします(もちろん、好みに合わせて名前を変更します)。のすべてのインスタンスが同じ単純型の値を持つように、これらを定義します。 default-databasenon-default-databasedefault-database

次に、 :を使用して、の2つのオカレンスがdefault-database同じ文字列値を持つことはできないことを指定します。xs:unique

<xs:unique name="dbname">
  <xs:selector xpath="database"/>
  <xs:field xpath="default-database"/>
</xs:unique>

のすべてのインスタンスはdefault-database同じ値を持っているため、この一意性の制約により、そのような要素は1つしか存在できなくなります。スキーマ全体は次のようになります。最初の簿記:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="qualified">

ここで、次の要素宣言databases

  <xs:element name="databases" type="databases">
    <xs:unique name="dbname">
      <xs:selector xpath="database"/>
      <xs:field xpath="default-database"/>
    </xs:unique>
  </xs:element>

そしてその複雑なタイプ:

  <xs:complexType name="databases">
    <xs:sequence minOccurs="0" maxOccurs="unbounded">
      <xs:element ref="database"/>
    </xs:sequence>
    <xs:attribute name="default" type="xs:string" use="optional"/>
  </xs:complexType>

さて、もう少し簿記databaseをします。正直に言うと、の宣言です。

  <xs:element name="database" type="database"/>

  <xs:complexType name="database">
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="host" type="xs:string"/>
      <xs:choice>       
        <xs:element name="default-database" type="empty"/>
        <xs:element name="non-default-database" type="empty"/>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>

default-databaseそして、簿記の最後のビット:のすべてのインスタンスが同じ値を持つことを保証するタイプ。(もちろん、これを実現する方法は他にもあります。これが最初に頭に浮かんだ方法です。)

  <xs:simpleType name="empty">
    <xs:restriction base="xs:string">
      <xs:enumeration value=""/>
    </xs:restriction>
  </xs:simpleType> 

</xs:schema>

あなたがあなたの既存のデザインと完全に結婚しているなら、私はあなたがXSD1.0でやりたいことをする方法を知りません。もちろん、XSD 1.1を使用できる場合は、databasesその上にアサーションを追加できます。

<xs:assert test="count(database[default = 'yes']) = 1"/>

しかし、上記の代替ソリューションが示すように、その設計とアサーションの使用はあなたの唯一の選択肢ではありません。

于 2012-10-28T02:05:06.010 に答える