2

C#のスキーマに対してXMLを検証する方法を理解しようとしています。XMLが単純で、名前空間要素を使用しない場合、すべてがうまくいくように見えます。しかし、XML名前空間を使用していると、問題が発生し始めます。

私が作成したいXMLは次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<SlideDeck xmlns:xy="http://something.com" xy:type="SlideDefinitions">
  <Slide>...</Slide>
  <Slide>...</Slide>
  ...
</SlideDeck>

これは、C#で次と同等のものを使用して作成できます。

XmlDocument xDoc = new XmlDocument();
XmlElement xSlideDeck = xDoc.CreateElement("SlideDeck");
xDoc.AppendChild(xSlideDeck);

xSlideDeck.SetAttribute("xmlns:xy", "http://something.com");
xSlideDeck.SetAttribute("type", "http://something.com", "SlideDefinitions");

そして、私はこれで生成されたXMLドキュメントを検証することを試みることができます:

xDoc.Schemas.Add("", "Schema.xsd");
xDoc.Validate(Handler);

検証するSchema.xsdファイルは、今のところかなり単純です。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="SlideDeck">
        <xs:complexType>
            <xs:sequence>
                <xs:choice maxOccurs="unbounded">
                    <xs:element ref="Slide"/>
                </xs:choice>
            </xs:sequence>
            <xs:attribute name="type" type="xs:string" use="required" />
        </xs:complexType>
    </xs:element>
    ... Slide Defined Here ...
</xs:schema>

検証を実行すると、次のエラーが発生します。

The 'http://something.com:type' attribute is not declared.
The required attribute 'type' is missing.

また、同じスキーマファイルでhttp://something.comを参照するXmlDocumentに追加のスキーマを追加しようとしました(「xy」名前空間にそれをプルすることを期待しています)。また、スキーマだけを適切なURIに追加しようとしました(URIなしでスキーマを除外しました)が、他の設定によっては、何も検証されません。ルートの「SlideDeck」要素もhttp://something.com名前空間に属するようにしてみました。

ここで何が起こっているのか考えてみませんか?出てくるXMLドキュメントのフォーマットはまったく変更できません。'SlideDeck'要素の前に'xy'を付けることも、他のすべての要素と一緒に行うこともできますが、それを実現するために、名前空間と接頭辞にuriを追加するためにすべてのコードを変更する必要はありません。大きな問題は、受信者に何を期待するかを警告するxmlns:xy定義とxy:type属性です。その他の変更は合理的です。プログラムが検証するXSDを制御することもできます。これは、プログラムを作成して検証するために、そこで変更を加えるのが最適な場合です。

4

1 に答える 1

1

スキーマは、SlideDeck要素がtype属性を持っている必要があることを示しています-両方ともnull名前空間にありますが、XMLでは、SlideDeck要素は名前空間に属性typeを持っていhttp://something.comます-したがって、エラーが発生します。

XMLを次のように変更する必要があります。

<SlideDeck type="SlideDefinitions">
  <Slide>. . . </Slide>
  <Slide>. . . </Slide>
  . . . 
</SlideDeck>

(つまり、名前空間を削除します)。

別の方法として、スキーマを変更して2つに分割する必要があります。

typeAttr.xsd:

<xs:schema 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:xy="http://something.com" 
  xmlns="http://something.com"
  targetNamespace="http://something.com"
  elementFormDefault="qualified"
  attributeFormDefault="qualified" >

  <xs:attribute name="type" type="xs:string" />

</xs:schema>

slide.xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:xy="http://something.com">
  <xs:import namespace="http://something.com" schemaLocation="typeAttr.xsd"/>
  <xs:element name="SlideDeck">
    <xs:complexType>
      <xs:sequence>
        <xs:choice maxOccurs="unbounded">
          <xs:element ref="Slide"/>
        </xs:choice>
      </xs:sequence>
      <xs:attribute ref="xy:type" use="required" />
    </xs:complexType>
  </xs:element>
  <xs:element name="Slide"></xs:element>
</xs:schema>

(同じディレクトリ内)。

このようにtypeして、別の名前空間で属性を定義すると、元のXMLが正しく検証されます。

于 2013-03-19T01:34:39.317 に答える