6

XSD を解析する必要がありますXSOMが、この XSD には循環インポートが含まれています。

A.xsd

<xs:schema xmlns=”ns1” targetNamespace=”ns1”&gt;
  <xs:import namespace=”ns2” schemaLocation=”B.xsd”/>
  <xs:element name=”MyElement” type=”xs:string”/>
</xs:schema>

B.xsd

<xs:schema xmlns=”ns2” targetNamespace=”ns2” xmlns:ns1=”ns1”&gt;
  <xs:import namespace=”ns1” schemaLocation=”A.xsd”/>
  <xs:complexType name="MyComplex">
    <xs:sequence>
      <xs:element ref="ns1:MyElement" minOccurs="0"/>
    <xs:sequence>
  <xs:complexType>
</xs:schema>

XSOM循環インポートにより既に定義されている要素が検出されるため、スキーマを解析できません。そこで、A で定義され、B で使用される要素を外部化することで、循環インポートを打破しようとしました。

C.xsd には、B で使用される A の要素が含まれています。これらの要素は A では使用されないことに注意してください。これらが A で定義されている理由を聞かないでください。

<xs:schema xmlns=”ns1” targetNamespace=”ns1”&gt;
  <xs:element name=”MyElement” type=”xs:string”/>
</xs:schema>

A.xsdは次のようになります

<xs:schema xmlns=”ns1” targetNamespace=”ns1”&gt;
  <xs:import namespace=”ns2” schemaLocation=”B.xsd”/>
</xs:schema>

B.xsd (A.xsd の代わりに C.xsd をインポート) は次のようになります。

<xs:schema xmlns=”ns2” targetNamespace=”ns2” xmlns:ns1=”ns1”&gt;
  <xs:import namespace=”ns1” schemaLocation=”C.xsd”/>
  <xs:complexType name="MyComplex">
    <xs:sequence>
      <xs:element ref="ns1:MyElement" minOccurs="0"/>
    <xs:sequence>
  <xs:complexType>
</xs:schema>

XSOMXSD を解析できます。しかし、今では次のコードでスキーマを作成できません:

SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
sf.setResourceResolver(new MyResourceResolver());

JDK 1.7 にバンドルされている標準実装を使用します。私は例外を受け取ります:

src-resolve: Cannot resolve the name 'ns1:MyElement' to a(n) 'element declaration' component.

問題は、リソース リゾルバーが B 名前空間に対して呼び出され、意味のある A 名前空間に対して呼び出されないことです。名前空間 A は A.xsd と C.xsd で共有されているため、リソース リゾルバーは C.xsd で定義されている要素を見つけることができません。

循環インポートは有効ですか? XSOMによって解析されてから読み込まれるように、循環インポートを中断することは可能SchemaFactoryですか?

4

1 に答える 1

8

一般的な質問について:

「循環インポートは有効ですか?」と尋ねます。循環性によって、スキーマ ドキュメント S[1]、S[2]、...、S[n] のチェーンが存在することを意味する場合、スキーマ ドキュメント S[1] はスキーマ ドキュメント S[2] を名前で参照し、S [2] から S[3]、... S[n-1] から S[n]、および S[n] から S[1] では、XSD 1.0 仕様または XSD 1.1 が明確に述べているとは思えません。いずれかの方法で。(一部の WG メンバーは、このトピックおよび関連するトピックについての考え方を明確にするよう WG を説得しようとしましたが、失敗しました。) 一部の実装では、循環インポート (およびその他の形式の循環性) をサポートしていますが、議論することは可能ではないと思います。あなたの実装が何か間違っているという仕様から。

一方、0 <= i <= n-1 の場合、S[i] は S[i+1] の名前空間をインポートし、S[n] は S の名前空間をインポートするようなサイクルがあることだけを意味する場合[1] したがって、そのようなサイクルは明らかに合法的である (場合によっては避けられない) と私は信じています。

私が推奨する回避策は次のとおりです。

  1. 何かを宣言するスキーマ ドキュメントでは、必要に応じて xs:import を使用しますが、インポートでスキーマの場所を指定しないでください。このような参照のサイクルは無害です。
  2. スキーマ プロセッサを呼び出すときは、読み取りたいすべてのスキーマ ドキュメントの完全なリストを渡してください。可能であれば、オプションまたは構成を介して、他のスキーマ ドキュメントを読み取らないように指示してください。
  3. スキーマ ドキュメントが検証時に複数のスキーマ ドキュメントを入力として受け入れない場合、読み取りたいすべてのものを参照する単一のスキーマ ドキュメントが必要な場合、またはスキーマ ドキュメントのリストを正しく取得する自信がない場合呼び出し時に、特定のスキーマの場所情報を使用して、読み取りたい他のスキーマ ドキュメントを含めてインポートするだけの最上位ドライバー ドキュメントを追加します。

あなたの場合、それは A.xsd と B.xsd (の元の形式) から xs:import/@schemaLocation 属性を削除し、形式のドライバー ドキュメントを追加することを意味します。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:import namespace="ns1" schemaLocation="A.xsd"/>
  <xs:import namespace="ns2" schemaLocation="B.xsd"/>
</xs:schema>

その効果は、スキーマ文書の他のスキーマ文書への参照に決してサイクルがないことを保証することです。これにより、XSD 実装が相互に矛盾する (場合によっては、それら自身と矛盾する) 非常に大規模なクラスのケースが排除されます。呼び出しが入力に異なる順序で名前を付けると、同じプロセッサが同じ入力に対して劇的に異なる結果を生成することがあります。

特定の質問について:

あなたの例では、A.xsd または C.xsd のいずれかによって ns2 がインポートされる必要はありません。どちらにも名前空間 ns2 内のコンポーネントへの参照が含まれていないためです。したがって、あなたの例のサイクルは無償のようです。

2 番目の例では、スキーマの読み込みに成功しないコードをいくつか指定します。しかし、そのコードには、特定のスキーマ ドキュメントへの参照はまったくありません。関連するものが表示されていない場合を除き、バリデーターが {ns1}MyElement の宣言を見つけられないのは不思議ではありません。

于 2013-02-12T19:41:46.050 に答える