1

検証対象の XSD スキーマを持つ XML ファイルを SQL にインポートしています。私が見つけた「問題」は、ファイル内のデータの一部が CDATA タグ内に含まれているが、対応する XML 要素が xsd:token として定義されていることです (W3Schools から - 「トークン データ型には文字も含まれていますが、XMLプロセッサは、ライン フィード、キャリッジ リターン、タブ、先頭と末尾のスペース、および複数のスペースを削除します。") 私が気付いたのは、型指定された XML 変数に対して単純な XQuery を SQL で実行したときに、CDATA 値から複数のスペースを削除する xsd:token ルールが適用されていたことです。ファイルのサプライヤーに戻る前に、正しい結果がどうあるべきかを再確認したかっただけです。以下のコードスニペットを参照してください...

CREATE XML SCHEMA COLLECTION dbo.MyTestSchema

AS

N'
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="ROOT">
    <xsd:complexType>
      <xsd:complexContent>
        <xsd:restriction base="xsd:anyType">
          <xsd:sequence>
            <xsd:element ref="Test" 
              minOccurs="0" maxOccurs="unbounded"/>
          </xsd:sequence>
        </xsd:restriction>
      </xsd:complexContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="Test" type="TestType"/>
  <xsd:simpleType name="TestType">
    <xsd:restriction base="xsd:token">
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>'

GO

DECLARE @XMLData varchar(MAX) = 
'<ROOT>
  <Test><![CDATA[0spaces]]></Test>
  <Test><![CDATA[1 space]]></Test>
  <Test><![CDATA[2  spaces]]></Test>
  <Test><![CDATA[3   spaces]]></Test>
</ROOT>'

DECLARE @XML xml = @XMLData
DECLARE @MyTestXML xml(CONTENT dbo.MyTestSchema) = @XMLData

;WITH WithoutSchema AS
(
    SELECT [Test] = NULLIF(T2.n.value('.', 'varchar(10)'), '')
    FROM @XML.nodes('/ROOT') AS T1(n)
    CROSS APPLY T1.n.nodes('Test') AS T2(n)
),
WithSchema AS
(
    SELECT [Test] = NULLIF(T2.n.value('.', 'varchar(10)'), '')
    FROM @MyTestXML.nodes('/ROOT') AS T1(n)
    CROSS APPLY T1.n.nodes('Test') AS T2(n)
)
SELECT [WithoutSchema] = N.Test, [WithSchema] = Y.Test
FROM WithoutSchema N
INNER JOIN WithSchema Y
    ON REPLACE(N.Test, ' ', '') = REPLACE(Y.Test, ' ', '')

GO

DROP XML SCHEMA COLLECTION dbo.MyTestSchema

GO

...結果は...

WithoutSchema WithSchema
------------- ----------
0spaces       0spaces
1 space       1 space
2  spaces     2 spaces
3   spaces    3 spaces

...ご覧のとおり、型指定されていない xml 変数を使用すると、CDATA テキストのスペースが保持されますが、型指定された変数 (xsd:token を使用) を使用するとスペースが取り除かれます。それが起こっている場合、xsd は非 CDATA 値にのみ適用されると思いましたか? スペースは、読み込んでいるデータに意味があるので、それが正しい動作である場合は、サプライヤーに報告する必要があります. 私はC#を介してデータを読み込もうとし、比較として得られた結果にスキーマを適用しようとしましたが、そこでの私のスキルは限られていたため、あまり成功しませんでした.

どうもありがとう!

4

1 に答える 1

1

これは正しいようです。最初の例では、XML は単なる生データです。生データを選択すると、生データが得られます。データには、空白を取得する空白が含まれています。2 番目の例では、データを明示的に正規化する型であるとデータを宣言します。これがxsd:token型の意味です (空白は折りたたまれ、先頭と末尾の空白は削除されます)。

型は、ほとんどのプログラミング言語のxsd:tokenシンボル宣言に似ています。通常、型と名前の間、または名前と代入の間にいくつのスペースを入れても問題ありません。たとえば、Java/C/C++ では、これはすべて有効です。

int         a = 5; // variable is called 'a' not '        a'.
int b
= 5; // not very readable, but the variable is called 'b'.

CDATA:についてCDATAは、XMLパーサーに文字を生データとして扱うように指示する方法にすぎませんが、他の情報/指示は引き続き適用されます。<そのため、文字を&XML ノードに挿入するより便利な方法です。ただし、データの意味と解釈は変わりません。データの意味と解釈はスキーマによって定義され、CDATA唯一のデータです (スキーマに従って解釈されます)。

于 2013-07-24T11:24:52.560 に答える