1

スキーマに対してカスタム XML ドキュメントを検証したいと考えています。このドキュメントには、それぞれが特定の属性を持つ任意の数の要素を持つ構造が含まれます。このようなもの:

<Root xmlns="http://tns">
  <Records>
    <FirstRecord attr='whatever'>content for first record</FirstRecord>
    <SecondRecord attr='whatever'>content for first record</SecondRecord>
    ...
    <LastRecord attr='whatever'>content for first record</LastRecord>
  </Records>
</Root>

XML ドキュメントの作成者は、任意の数のレコードを含めることができ、それぞれに任意の名前を付けることができます。XML Schema に対してこれを検証するにはどうすればよいですか?

スキーマで適切な構造型を指定しようとしましたが、適切な場所でそれを参照する方法がわかりません:

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

    <xs:complexType name="RecordType"> <!-- This is my record type -->
        <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="Root">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="1" maxOccurs="1" name="Records">
                    <!-- This is where records should go -->
                    <xs:complexType /> 
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>
4

2 に答える 2

2

あなたが説明することは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」のままにすることができます。

于 2013-02-01T18:19:53.940 に答える
0

これは XSD だけでは不可能だと思います。

あなたが言う時

任意の数のレコードで、それぞれに任意の名前が付けられます。

そのため、<xs:any/>要素を使用する必要がありますが! として宣言された要素を持っていると、そのany下の属性を検証できません..

だから..答えはNOです!

于 2013-02-01T13:35:18.423 に答える