34

多分それは私ですが、XSDを持っている場合

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="User">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="GivenName" />
                <xs:element name="SurName" />
            </xs:sequence>
            <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
        </xs:complexType>
    </xs:element>
</xs:schema>

このドキュメントのスキーマを定義する

<?xml version="1.0" encoding="utf-8" ?>
<User ID="1">
    <GivenName></GivenName>
    <SurName></SurName>
</User>

EmailAddress などの別の要素を追加し、順序を混同すると、検証に失敗します。

<?xml version="1.0" encoding="utf-8" ?>
<User ID="1">
    <SurName></SurName>
    <EmailAddress></EmailAddress>
    <GivenName></GivenName>
</User>

ドキュメントに EmailAddress を追加して、オプションとしてマークしたくありません。

ドキュメントが満たす必要のある最低限の要件を検証する XSD が必要なだけです。

これを行う方法はありますか?

編集:

xs:anyより多くの要素を許可するために内部で使用できることを以下に指摘した marc_s はxs:sequence、残念ながら、要素の順序を維持する必要があります。

xs:allまたは、要素の順序を強制しない whichを使用できますが、残念ながら、xs:anyその中に配置することはできません。

4

5 に答える 5

57

あなたの問題には解決策がありますが、きれいではありません。理由は次のとおりです。

非決定論的コンテンツ モデルの違反

W3C XML Schema の本質に触れました。あなたが求めているもの — 可変順序可変未知要素 — は、XSD の最も困難でありながら最も基本的な原則であるNon-Ambiguityのルール、またはより正式にはUnique Particle Attribution Constraintに違反しています。

コンテンツ モデルは、検証中に [..] シーケンス内の各アイテムが、そのアイテムのコンテンツや属性を調べることなく、シーケンスの残りのアイテムに関する情報なしで一意に決定できるように形成する必要があります。

通常の英語では、XML が検証され、XSD プロセッサが遭遇し<SurName>た場合、最初に が続くかどうかをチェックせずに検証できる必要があります<GivenName>。あなたのシナリオでは、これは不可能です。この規則は、有限ステート マシンによる実装を許可するために存在します。これにより、実装がかなり簡単で高速になります。

これは最も議論の多い問題の 1 つであり、SGML と DTD (コンテンツ モデルは決定論的である必要があります) および XML の遺産であり、デフォルトで、要素の順序が重要であると定義されています(したがって、反対のことを試みて順序を変更します)。重要ではない、難しい)。

Marc_s が既に示唆しているように、Relax_NG は、非決定論的なコンテンツ モデルを可能にする代替手段です。しかし、W3C XML スキーマに行き詰まっている場合はどうすればよいでしょうか?

機能しない半有効なソリューション

あなたはすでにそれxs:allが非常に制限的であることにお気づきでしょう。理由は簡単です。同じ非決定論的なルールが適用され、1 より大きい とシーケンスが許可されないのはそのためxs:anyですmin/maxOccurs

choiceまた、 、 、のあらゆる種類の組み合わせsequenceを試したことがあるかもしれませんany。このような無効な状況が発生したときに Microsoft XSD プロセッサがスローするエラーは次のとおりです。

エラー: 要素 ' http://example.com/Chad:SurName 'の複数の定義により、コンテンツ モデルがあいまいになります。コンテンツ モデルは、要素情報アイテム シーケンスの検証中に、シーケンス内の各アイテムを順番に検証しようとする直接的、間接的、または暗示的に含まれる粒子が、コンテンツまたは属性を調べることなく一意に決定できるように形成する必要があります。そのアイテム、およびシーケンスの残りのアイテムに関する情報なし。

O'Reilly の XML Schema (そうです、この本には欠点があります) では、これが見事に説明されています。さらに、本の一部はオンラインで入手できます。Unique Particle Attribution Ruleに関するセクション 7.4.1.3を読むことを強くお勧めします。その説明と例は、私が得ることができるよりもはるかに明確です。

1 つの実用的なソリューション

ほとんどの場合、非決定論的設計から決定論的設計に移行することが可能です。これは通常は見栄えがよくありませんが、W3C XML スキーマに固執する必要がある場合や、厳密ではない規則を XML に絶対に許可する必要がある場合の解決策です。あなたの状況の悪夢は、1 つのこと (2 つの事前定義された要素) を強制したいと同時に、それを非常に緩くしたいことです (順序は関係なく、前と後の間で何でも構いません)。適切なアドバイスをするのではなく、解決策に直接導くだけだとすると、次のようになります。

<xs:element name="User">
    <xs:complexType>
        <xs:sequence>
            <xs:any minOccurs="0" processContents="lax" namespace="##other" />
            <xs:choice>
                <xs:sequence>                        
                    <xs:element name="GivenName" />
                    <xs:any minOccurs="0" processContents="lax" namespace="##other" />
                    <xs:element name="SurName" />
                </xs:sequence>
                <xs:sequence>
                    <xs:element name="SurName" />
                    <xs:any minOccurs="0" processContents="lax" namespace="##other" />
                    <xs:element name="GivenName" />
                </xs:sequence>
            </xs:choice>
            <xs:any minOccurs="0" processContents="lax" namespace="##any" />
        </xs:sequence>
        <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
    </xs:complexType>
</xs:element>

上記のコードは実際に機能します。しかし、いくつかの注意点があります。1 つ目は、名前空間としてxs:anywithです。最後のものを除いて、 を##other使用することはできません。これは、代わりに要素 like を使用することを許可し、 の定義があいまいになることを意味します。##anyGivenNameUser

2 つ目の注意点は、このトリックを 2 つまたは 3 つ以上で使用する場合は、すべての組み合わせを書き留める必要があるということです。メンテナンスの悪夢。そのため、次のことを思いつきます。

提案された解決策、バリアブル コンテンツ コンテナーのバリアント

定義を変更してください。これには、読者やユーザーにとってより明確であるという利点があります。また、メンテナンスが容易になるというメリットもあります。一連のソリューション全体が XFront hereで説明されています。これは、Oleg の投稿から既に見たかもしれない読みにくいリンクです。すばらしい読み物ですが、ほとんどの場合、可変コンテンツ コンテナー内に 2 つの要素という最小要件があることを考慮していません。

あなたの状況 (想像以上に頻繁に起こる) に対する現在のベスト プラクティス アプローチは、データを必須フィールドと非必須フィールドに分割することです。要素を追加する<Required>か、反対のことを行い、要素を追加します(またはそれをProperties、またはOptionalData<ExtendedInfo>と呼びます)。これは次のようになります。

<xs:element name="User2">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="GivenName" />
            <xs:element name="SurName" />
            <xs:element name="ExtendedInfo" minOccurs="0">
                <xs:complexType>
                    <xs:sequence>
                        <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" namespace="##any" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

現時点では理想的とは言えないかもしれませんが、少し成長させてください。固定要素の順序付けられたセットを持つことは、それほど大したことではありません。W3C XML スキーマのこの明らかな欠陥について不満を言うのはあなただけではありませんが、前述したように、それを使用する必要がある場合は、その制限を受け入れるか、開発の負担を受け入れる必要があります。より高い所有コストでこれらの制限を回避します。

代替ソリューション

これはもうご存知だと思いますが、属性の順序はデフォルトでは未定です。すべてのコンテンツが単純なタイプである場合は、代わりに属性をより豊富に使用することを選択できます。

最後に一言

どのようなアプローチをとっても、データの多くの検証可能性が失われます。多くの場合、コンテンツ プロバイダーがコンテンツ タイプを追加できるようにする方が適切ですが、それが確認できる場合に限られます。laxこれは、からstrictprocessing に切り替え、型自体をより厳密にすることで実行できます。しかし、厳しすぎるのもよくありません。適切なバランスは、直面しているユースケースを判断する能力と、特定の実装戦略のトレードオフと比較検討する能力に依存します。

于 2010-08-05T00:38:26.823 に答える
6

marc_sの回答とコメントでのディスカッションを読んだ後、少し追加することにしました。

あなたの問題チャドの完璧な解決策はないように思えます。XSD で拡張可能なコンテンツ モデルを実装する方法はいくつかありますが、私が知っているすべての実装にはいくつかの制限があります。拡張可能な XSD を使用する予定の環境について書いていないため、環境に実装できる方法を選択するのに役立つリンクをいくつかお勧めします。

  1. http://www.xfront.com/ExtensibleContentModels.html (またはhttp://www.xfront.com/ExtensibleContentModels.pdf ) およびhttp://www.xfront.com/VariableContentContainers.html
  2. http://www.xml.com/lpt/a/993 (またはhttp://www.xml.com/pub/a/2002/07/03/schema_design.html )
  3. http://msdn.microsoft.com/en-us/library/ms950793.aspx
于 2010-08-01T20:33:00.463 に答える
4

<xs:any>拡張性のための要素を使用してスキーマを拡張できるはずです。詳細については、 W3Schoolsを参照してください。

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="User">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="GivenName" />
                <xs:element name="SurName" />
                <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax" />
            </xs:sequence>
            <xs:attribute name="ID" type="xs:unsignedByte" use="required" />
        </xs:complexType>
    </xs:element>
</xs:schema>

を追加するprocessContents="lax"と、.NET XML 検証が成功するはずです。

詳細については、xs:anyの MSDN ドキュメントを参照してください。

更新:より柔軟で、それほど厳密でない検証が必要な場合は、XML のスキーマを定義する他の方法 ( RelaxNGなど) を検討することをお勧めします。XML Schema は、意図的に、そのルールに関してかなり厳密であるため、この仕事に適したツールではない可能性があります。

于 2010-07-27T20:55:27.220 に答える
1

まあ、いつでも DTD を使用できます :-) ただし、DTD では順序付けも規定されています。「順序付けされていない」文法による検証は、非常にコストがかかります。xsd:choice で遊ぶこともできますが、最小値と最大値が発生しますが、おそらくボークも発生します。XSD 拡張機能や派生スキーマを作成することもできます。

あなたが問題を提起した方法は、XSDがまったく必要ないように見えます。それを読み込んで、XPathsで必要な最小値を検証することはできますが、XSDが遍在する標準になってから何年経っても、XSDに抗議するだけでは、本当に、本当にどこにも行きません.

于 2010-08-04T14:15:08.493 に答える
1

RelaxNG を使用できれば、この問題を簡潔に解決できます。決定論はスキーマの要件ではありません。RNG または RNC スキーマを XSD に変換できますが、この場合は概算になります。それがあなたの使用に十分かどうかはあなた次第です。

この場合の RNC スキーマは次のとおりです。

start = User
User = element User {
   attribute ID { xsd:unsignedByte },
   ( element GivenName { text } &
     element SurName { text } &
     element * - (SurName | GivenName) { any })
}

any = element * { (attribute * { text } | text | any)* }

any ルールは、整形式の XML フラグメントに一致します。したがって、これには User 要素に任意の順序でテキストを含む GivenName および SurName 要素を含める必要があり、ほとんどすべてを含む他の要素を許可します。

于 2013-08-12T19:02:11.380 に答える