Я импортирую некоторые XML-файлы в SQL, которые имеют XSD-схему, с которой я проверяю. «Проблема», которую я обнаружил, заключается в том, что некоторые данные в файлах содержатся в тегах CDATA, но соответствующий элемент XML определяется как токен xsd: (из W3Schools - «Тип данных токена также содержит символы, но XML процессор удалит линейные каналы, возврат каретки, вкладки, начальные и конечные пробелы и несколько пробелов. "). Я заметил, что когда я запускал простой XQuery в SQL против типизированной переменной XML, он применял правила xsd: token для удаления нескольких пробелов для значений CDATA. Прежде чем я вернусь к поставщику файла, я просто хотел бы проверить, какой должен быть правильный результат. Ниже фрагмент кода ...Должен ли XML Parser применять ограничения XSD-схемы для CDATA?
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: токен) лишает их. Должно ли это происходить, я думал, что xsd применяется только к значениям, отличным от CDATA? Пространства имеют смысл в данных, которые мы загружаем, поэтому, если это правильное поведение, я должен поднять с поставщиком. Я попытался прочитать данные с помощью C# и применить схему к тем результатам, которые дали в качестве сравнения, но мои навыки там ограничены, поэтому у них не было большого успеха.
Большое спасибо!
Спасибо за ваш ответ. Я вернусь к нашему поставщику, потому что мы получаем еще один файл (csv) со списком значений «первичного ключа», которые мы должны присоединиться к нашим файлам XML в соответствующем поле. Проблема в том, что в некоторых случаях файл csv содержит двойные пробелы, которые затем не ссылаются на значение, загруженное XML-файлом (с применением их схемы), которое превратилось в одно пространство, так что теперь мы получаем потерянные данные :) – user2614273