検証対象の 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#を介してデータを読み込もうとし、比較として得られた結果にスキーマを適用しようとしましたが、そこでの私のスキルは限られていたため、あまり成功しませんでした.
どうもありがとう!