OpenXml renvoie null pour les éléments dans XML

Declare @xml xml, @y int set @xml= '<ContactUpdates> <Contact VendorID="4"><LastName>McCrystle</LastName> <FirstName>Timothy</FirstName> </Contact> <Contact VendorID="10"> <LastName>Flynn</LastName> <FirstName>Erin</FirstName> </Contact></ContactUpdates>' Exec sp_xml_preparedocument @y output, @xml; Select * from openxml(@y,'/ContactUpdates/Contact') With (VendorID Varchar(20), LastName Varchar(30), FirstName Varchar(30))` 

Le résultat est

Je ne sais pas où l'erreur a été commise. S'il vous plaît aidez-moi avec cela.

Vous avez un mélange de projections axées sur les attributes et cinputs sur les éléments. La raison pour laquelle VendorId est mappée, mais pas pour les deux éléments, est que l'atsortingbut censortingc est la valeur par défaut. Dans un scénario de hiérarchie mixte / complexe, comme xpath ici , vous devrez fournir explicitement les mappages xpath :

 Exec sp_xml_preparedocument @y output, @xml; Select * from openxml(@y,'/ContactUpdates/Contact') With (VendorID Varchar(20) '@VendorID', -- Atsortingbute LastName Varchar(30) 'LastName', -- Element FirstName Varchar(30) 'FirstName'); -- Element 

modifier

Quelque chose d'intéressant à noter est que l'atsortingbut flags est, bien, un style bit [flag]. Cela signifie que vous pouvez OU les options set. 1 est centré sur l'atsortingbut, et 2 centré sur l'élément, donc 1 | 2 = 3 1 | 2 = 3 vous donnera les deux:

 Exec sp_xml_preparedocument @y output, @xml; Select * from openxml(@y,'/ContactUpdates/Contact', 3) With (VendorID Varchar(20), LastName Varchar(30), FirstName Varchar(30)); -- Remember to release the handle with sp_xml_removedocument 

Cependant, je ne crois pas que ce soit une bonne pratique – il ne transmet pas beaucoup au développeur, et il a probablement des implications de performances négatives étant donné qu'il est less spécifique que le xpath exact.

Utilisez le support XQuery natif approprié dans SQL Server:

 SELECT VendorID = xc.value('@VendorID', 'int'), FirstName = xc.value('(FirstName)[1]', 'varchar(50)'), LastName = xc.value('(LastName)[1]', 'varchar(50)') FROM @xml.nodes('/ContactUpdates/Contact') AS XT(XC) 

Vous donne facilement cette belle sortie:

entrez la description de l'image ici

Cela devrait vous aider

 SELECT VendorID = Container.value('(@VendorID)[1]', 'varchar(50)'), LastName = Container.value('(LastName)[1]', 'varchar(50)'), FirstName = Container.value('(FirstName)[1]', 'varchar(50)') FROM (SELECT @xml Columndata) a CROSS APPLY Columndata.nodes('/ContactUpdates/Contact') AS T(Container) 

Edité selon le commentaire de Stuart.

 SELECT VendorID = Container.value('(@VendorID)[1]', 'varchar(50)'), LastName = Container.value('(LastName)[1]', 'varchar(50)'), FirstName = Container.value('(FirstName)[1]', 'varchar(50)') FROM @xml.nodes('/ContactUpdates/Contact') AS T(Container)