あなたが説明することはXSD 1.1で可能であり、XSD 1.0でも非常によく似たことが可能ですが、それが賢明な設計であるとは言えません。
XML 語彙では、要素タイプは通常、情報のタイプに関する関連情報を伝達します。これは、ほとんどの XML スキーマ言語で検証を推進するために使用される要素タイプの名前です。あなたが説明する設計は、Java でオブジェクト クラスを定義できるかどうか、または C で構造体を定義できるかどうかを尋ねるのに少し似ています。メンバーが任意の名前を持つことができるという制約に従います。値が 42 の整数。それまたはそのようなことは十分に可能かもしれませんが、ほとんどの経験豊富な設計者は、これが通常の問題を解決するための正しい方法ではないことを強く感じるでしょう。
一方、システムを使って通常とは異なることを行うと、システムを効果的に使用する方法を学ぶのに役立つ場合があります。(システムを完全に悪用するまで、システムをよく知ることはできない、と私の友人はかつて言いました。) したがって、私の答えは 2 つの部分で構成されています。代わりは。
XSD 1.1 で必要と思われる言語を指定する最も簡単な方法は、(1) Records のすべての子には 'attr' 属性があり、(2) Records の子には属性がないことを示す、Records 要素のアサーションを定義することです。子供。次のようなものがあります。
...
<xs:element minOccurs="1" maxOccurs="1" name="Records">
<xs:complexType>
<xs:sequence>
<xs:any/>
</xs:sequence>
<xs:assert
test="every $child in * satisfies $child/@attr"/>
<xs:assert
test="not(*/*)"/>
</xs:complexType>
</xs:element>
...
ご覧のとおり、これは InfantPro'Aravind' が説明したものと非常によく似ています。型代入ではなくアサーションを使用して課す制約を課すことにより、InfantPro'Aravind' によって特定された問題を回避します。
XSD 1.0では、アサーションは利用できません。あなたが説明するデザインに近づくために私が考えることができる唯一の方法は、レコードの子としてレコードと呼ぶ抽象要素を定義し、要素がこれは、Record の子として実際に発生し、この抽象型に代入可能であると宣言されます (これには、それらの型が RecordType 型から派生する必要があります)。スキーマは次のようになります。
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Records">
<xs:complexType>
<xs:sequence>
<xs:element name="Record"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="RecordType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="attr"
type="xs:string"
use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:element name="Record"
type="RecordType"
abstract="true"/>
スキーマの他の場所 (おそらく別のスキーマ ドキュメント) で、FirstRecord などを宣言し、それらが Record の代用可能であることを指定する必要があります。
<xs:element name="FirstRecord" substitutionGroup="Record"/>
<xs:element name="SecondRecord" substitutionGroup="Record"/>
<xs:element name="ThirdRecord" substitutionGroup="Record"/>
...
あるレベルでは、これはあなたの説明と一致しますが、FirstRecord、SecondRecord などを宣言する必要はなかったと思います。
あなたが説明したことを XSD が実行できる方法を説明しましたが、これらのアプローチのいずれもお勧めしません。代わりに、XSD でより自然に動作するように、XML ボキャブラリを別の方法で設計します。
指定した設計では、すべてのレコードが同じタイプを持っているように見えますが、要素のコンテンツに加えて、異なる名前 (FirstRecord、SecondRecord など) を持つことで、特定の量の追加情報を伝えることができます。 . この追加情報は、属性で簡単に伝えることができます。これにより、レコードを抽象要素ではなく具体的な要素として指定し、追加の「代替名」属性を与えることができます。サンプル データは次のような形式になります。
<Root xmlns="http://tns">
<Records>
<Record
alternate-name="FirstRecord"
attr='whatever'>content for first record</Record>
<Record
alternate-name="SecondRecord"
attr='whatever'>content for first record</Record>
...
<Record
alternate-name="LastRecord"
attr='whatever'>content for first record</Record>
</Records>
</Root>
これは、文字列「FirstRecord」を属性値ではなく要素タイプ名にすることに神秘的またはその他の重要性を与えるかどうかによって、多かれ少なかれ許容されます。
あるいは、設計のポイントは、レコードに任意の構造の要素の任意のシーケンスを含めることを許可することであると言うことができます (このため、制限xs:string
は例の成果物にすぎず、実際には実際には望ましくありません)。各レコードについて、「attr」属性に記録された情報があるためです。これを指定するのは簡単です: 「Record」を「attr」属性を持つ具象要素として定義し、任意の XML 要素である 1 つの子を受け入れます。
<xs:element name="Record">
<xs:complexType>
<xs:sequence>
<xs:any processContents="lax"/>
</xs:sequence>
<xs:attribute name="attr"
use="required"
type="xs:string"/>
</xs:complexType>
</xs:element>
FirstRecord、SecondRecord などを検証 (および宣言) するかどうかに応じて、「processContents」属性の値を「strict」または「skip」に変更するか、「lax」のままにすることができます。