how to read this xml in sql server - sql

I am having xml as result for webservice api . i need to parse the result and update to database table. my xml is below . it is a response text.
<?xml version="1.0" encoding="utf-8"?>
<double>1</double>
Sqlserver 2008 Code :
declare #xml xml, #rate DECIMAL(10,4)
set #xml=REPLACE(#ResponseText ,'encoding="utf-8"','')
select #rate= #xml.value('(/double)[1]','decimal')
I want to get the value of double but it always return the null .
Please help me out .
Hi , have Done changes as per your suggestion still no getting.
declare #xml XML
DECLARE #responsetext VARCHAR(900)
declare #rate DECIMAL(10,4)
SET #responsetext = '<?xml version="1.0" encoding="utf-8"?>
<double xmlns="http://www.webserviceX.NET/">1</double>'
set #xml=REPLACE(#ResponseText ,'encoding="utf-8"','')
select #rate= #xml.value('(/double)[1]','decimal')
select #rate

You need to declare the namespace when querying using the value() Method.
Change the first parameter of value() from
'(/double)[1]'
to
'declare namespace x="http://www.webserviceX.NET/"; (/x:double)[1]'
So the full example will look like this
declare #xml XML
DECLARE #responsetext VARCHAR(900)
declare #rate DECIMAL(10,4)
SET #responsetext = '<?xml version="1.0" encoding="utf-8"?>
<double xmlns="http://www.webserviceX.NET/">1</double>'
set #xml=REPLACE(#ResponseText ,'encoding="utf-8"','')
select #rate= #xml.value('declare namespace x="http://www.webserviceX.NET/"; (/x:double)[1]','decimal')
select #rate
which should return 1.000 (decimal)

DECLARE #X XML = '<?xml version="1.0" encoding="utf-8"?>
<double xmlns="http://www.webserviceX.NET/">1</double>'
SELECT #X.value ('declare namespace x="http://www.webserviceX.NET/"; (/x:double)[1]', 'decimal')
Updated to reflect your use of namespace; the general point is that you don't need to do string manipulation to make this work. The header is fully supported. However, namespaces are important.

Not an answer, just some sample code - this returns a 1, not a NULL:
declare #xml xml, #rate DECIMAL(10,4)
declare #ResponseText varchar(900)
set #ResponseText = '<?xml version="1.0" encoding="utf-8"?> <double>1</double>'
set #xml=REPLACE(#ResponseText ,'encoding="utf-8"','')
select #rate= #xml.value('(/double)[1]','decimal')
select #rate

Related

Problem with parsing XML with multiple namespace into SQL

I've got problem with parsing informations from XML into SQL with double namespace.
Have a look at this code:
DECLARE #Handle AS INT; -- The handle of the XML data, passed to sp_xml_preparedocument
DECLARE #Xml AS NVARCHAR(1000); -- The XML document for this example
SET #Xml = N'
<SiBikNet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://www.ws.bik.pl/ws/ki/2v2/types">
<BIK_REQUEST>
<siBikNetResponse>
<consentDate>2018-07-29</consentDate>
<citizenshipStatus>citizen</citizenshipStatus>
<nationality>PL</nationality>
<pesel>123</pesel>
</siBikNetResponse>
</BIK_REQUEST>
</SiBikNet>';
EXEC sys.sp_xml_preparedocument #Handle OUTPUT , #Xml, N'<SiBikNet xmlns:t="https://www.ws.bik.pl/ws/ki/2v2/types"/>'; --Prepare a parsed document
SELECT *
FROM
OPENXML(#Handle,'/t:SiBikNet/t:BIK_REQUEST/t:siBikNetResponse', 2)
WITH ( nationality NVARCHAR(10) 't:nationality',
pesel NVARCHAR(10) 't:pesel '
);
EXEC sys.sp_xml_removedocument #Handle;
Which gives me proper output in forms of table with 2 columns.
But when I will add one row with double namespace: then I cannot parse this informations :
DECLARE #Handle AS INT; -- The handle of the XML data, passed to sp_xml_preparedocument
DECLARE #Xml AS NVARCHAR(1000); -- The XML document for this example
SET #Xml = N'
<SiBikNet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://www.ws.bik.pl/ws/ki/2v2/types">
<BIK_REQUEST xmlns="">
<siBikNetResponse>
<consentDate>2018-07-29</consentDate>
<citizenshipStatus>citizen</citizenshipStatus>
<nationality>PL</nationality>
<pesel>123</pesel>
</siBikNetResponse>
</BIK_REQUEST>
</SiBikNet>';
EXEC sys.sp_xml_preparedocument #Handle OUTPUT , #Xml, N'<SiBikNet xmlns:t="https://www.ws.bik.pl/ws/ki/2v2/types"/>'; --Prepare a parsed document
SELECT *
FROM
OPENXML(#Handle,'/t:SiBikNet/t:BIK_REQUEST/t:siBikNetResponse', 2)
WITH ( nationality NVARCHAR(10) 't:nationality',
pesel NVARCHAR(10) 't:pesel '
);
EXEC sys.sp_xml_removedocument #Handle;
Can anyone help ?
When I get stuck with anonymous namespaces or oddball namespace combinations, the simplest way is to just use the XPath function local-name(). Like this:
DECLARE #Handle AS INT; -- The handle of the XML data, passed to sp_xml_preparedocument
DECLARE #Xml AS NVARCHAR(1000); -- The XML document for this example
SET #Xml = N'
<SiBikNet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://www.ws.bik.pl/ws/ki/2v2/types">
<BIK_REQUEST xmlns="">
<siBikNetResponse>
<consentDate>2018-07-29</consentDate>
<citizenshipStatus>citizen</citizenshipStatus>
<nationality>PL</nationality>
<pesel>98070902702</pesel>
</siBikNetResponse>
</BIK_REQUEST>
</SiBikNet>';
EXEC sys.sp_xml_preparedocument #Handle OUTPUT , #Xml, N'<SiBikNet xmlns:t="https://www.ws.bik.pl/ws/ki/2v2/types"/>'; --Prepare a parsed document
SELECT *
FROM
OPENXML(#Handle,'/*[local-name()="SiBikNet"]/*[local-name()="BIK_REQUEST"]/*[local-name()="siBikNetResponse"]', 2)
WITH ( nationality NVARCHAR(10) ,--'t:nationality',
pesel NVARCHAR(10) --'t:pesel '
);
EXEC sys.sp_xml_removedocument #Handle;

getting NULL in sql table while parsing xml in SQL Server 2008

I'm trying to parse an XML document with a query.
Here is a sample of my XML:
<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://bbhgtm.gov.com/oos/export/1" xmlns:oos="http://bbhgtm.gov.com/oos/types/1">
<notificationOK>
<oos:id>8373125</oos:id>
<oos:notificationNumber>0173200001513000422</oos:notificationNumber>
Here is my query
declare #hdoc int
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x,
'
<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:q="http://bbhgtm.gov.com/oos/export/1"
xmlns:oos="http://bbhgtm.gov.com/oos/types/1"/>
'
select *
from openxml(#hdoc, '/notificationOK/oos:id/oos:notificationNumber/', 1)
WITH(
versionNumber int 'oos:versionNumber'
,createDate datetime 'oos:createDate'
)
EXEC sp_xml_removedocument #hdoc
But I'm getting NULL in my SQL table.
What to do?
You're ignoring the XML namespaces on your XML document!
<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://bbhgtm.gov.com/oos/export/1"
xmlns:oos="http://bbhgtm.gov.com/oos/types/1">
See those xmlns=..... and xmlns:oos=...... attributes? Those define XML namespaces that need to be taken into account when querying!
Also, I'd recommend to use the built-in, native XQuery support rather than the clumsy OPENXML code.
Try this code here:
DECLARE #input XML =
'<export xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://bbhgtm.gov.com/oos/export/1"
xmlns:oos="http://bbhgtm.gov.com/oos/types/1">
<notificationOK>
<oos:id>8373125</oos:id>
<oos:notificationNumber>0173200001513000422</oos:notificationNumber>
</notificationOK>
</export>'
;WITH XMLNAMESPACES('http://bbhgtm.gov.com/oos/types/1' AS oos,
DEFAULT 'http://bbhgtm.gov.com/oos/export/1')
SELECT
id = XC.value('(oos:id)[1]', 'int'),
NotificationNumber = XC.value('(oos:notificationNumber)[1]', 'bigint')
FROM
#input.nodes('/export/notificationOK') AS XT(XC)
This results in an output something like this:

OpenXML Import XML file to SQL server table

I am trying to set up an SQL job to import an XML file into an SQL Server table. Using OPENXML, I can't seem to select the specific data I need from the file. Here's my code and XML data. I am trying to select Facility and Entity_Code but when I run the code, these fields appear as blank.
I would like to transfer these fields into their own table.
Thanks in advance.
Declare #x xml
select #x=p
from OPENROWSET(Bulk'\\vmirsdh01\fast_data\Small.xml', SINGLE_BLOB) as T(P)
Select #x
Declare #hdoc int
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x
Select *
FROM OPENXML (#hdoc,'/Report/Tablix1/Details_Collection/Details',0)
with(Facility nvarchar(255) '#Facility',
Entity_Code nvarchar(255) '#Entity_Code')
exec sp_xml_removedocument #hdoc
'************ XML
<?xml version="1.0" encoding="utf-8"?><Report xsi:schemaLocation="T-Report https://csre.xxx.com%2FDevelopment%20Folder%2FIand%2FT-Report&rs%3ACommand=Render&rs%3AFormat=XML&rs%3ASessionID=4keav12uayp33ve3uczpgmfr&rc %3ASchema=True" Name="T-Report" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="T_Report">
<Tablix1>
<Details_Collection><Details Facility="Fxx" Tool_Type="Base Build" Entity_Code="EquiP1" /></Details_Collection>
</Tablix1>
</Report>
Here is an executable version
Declare #x xml
select #x='<?xml version="1.0" encoding="utf-8"?><Report xsi:schemaLocation="T-Report https://csre.xxx.com%2FDevelopment%20Folder%2FIand%2FT-Report&rs%3ACommand=Render&rs%3AFormat=XML&rs%3ASessionID=4keav12uayp33ve3uczpgmfr&rc %3ASchema=True" Name="T-Report" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="T_Report">
<Tablix1>
<Details_Collection><Details Facility="Fxx" Tool_Type="Base Build" Entity_Code="EquiP1" /></Details_Collection>
</Tablix1>
</Report>'
Declare #hdoc int
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x
Select *
FROM OPENXML (#hdoc,'/Report/Tablix1/Details_Collection/Details',0)
with(Facility nvarchar(255) '#Facility',
Entity_Code nvarchar(255) '#Entity_Code')
exec sp_xml_removedocument #hdoc
You have a default namespace that you need to take into consideration xmlns="T_Report".
Using the XML variable directly your query would look like
with xmlnamespaces(default 'T_Report')
select D.X.value('#Facility', 'nvarchar(255)'),
D.X.value('#Entity_Code', 'nvarchar(255)')
from #x.nodes('/Report/Tablix1/Details_Collection/Details') as D(X)
If you for some reason want to use openxml you need to declare the namespace in the third parameter to sp_xml_preparedocument.
EXEC sp_xml_preparedocument #hdoc OUTPUT, #x, '<root xmlns:xx="T_Report"/>'
Select *
FROM OPENXML (#hdoc,'/xx:Report/xx:Tablix1/xx:Details_Collection/xx:Details',0)
with(Facility nvarchar(255) '#Facility',
Entity_Code nvarchar(255) '#Entity_Code')
exec sp_xml_removedocument #hdoc
Your XML has an opening tag of <Report> but your query is for an opening tag called <Result>.
While I can't swear that everything will work after you fix that (I don't do much with OPENXML) I'm fairly confident that that is a problem.

TSQL - use variables in OPENXML

Suppose I have a query like this -
SELECT * FROM
OPENXML(#i, '/root/authors', 2)
WITH authors
Now, I want to pass '/root' via a parameter/variable like -
DECLARE #nodeName varchar(MAX) ----> EDIT: Solution- Use fixed length instead of MAX
SET #nodeName = '/root'
and use #nodeName instead. Then concatenate the rest of the elements dynamically.
I am getting error just by using #nodeName in the OPENXML parameter.
Better to use the new XML type.
create proc [dbo].[getLocationTypes](#locationIds XML,
#typeIds XML=null)
as
begin
set nocount on
SELECT locationId, typeId
FROM xrefLocationTypes
WHERE locationId
IN (SELECT Item.value('.', 'int' )
FROM #locationIDs.nodes('IDList/ID') AS x(Item))
AND (typeId IN
(SELECT Item.value('.', 'int' )
FROM #typeIds.nodes('IDList/ID') AS x(Item)))
ORDER BY 1, 2
end
And then you would call this like:
EXECUTE dbo.getLocationTypes '<IDList><ID>1</ID><ID>3</ID></IDList>',
'<IDList><ID>200</ID><ID>300</ID><ID>400</ID></IDList>'
I tried the following in SQL 2008 R2 and it works fine.
DECLARE #idoc int
DECLARE #doc varchar(1000)
SET #doc ='
<ROOT>
<Customer CustomerID="VINET" ContactName="Paul Henriot">
<Order CustomerID="VINET" EmployeeID="5" OrderDate="1996-07-04T00:00:00">
<OrderDetail OrderID="10248" ProductID="11" Quantity="12"/>
<OrderDetail OrderID="10248" ProductID="42" Quantity="10"/>
</Order>
</Customer>
<Customer CustomerID="LILAS" ContactName="Carlos Gonzlez">
<Order CustomerID="LILAS" EmployeeID="3" OrderDate="1996-08-16T00:00:00">
<OrderDetail OrderID="10283" ProductID="72" Quantity="3"/>
</Order>
</Customer>
</ROOT>'
--Create an internal representation of the XML document.
EXEC sp_xml_preparedocument #idoc OUTPUT, #doc
-- Execute a SELECT statement that uses the OPENXML rowset provider.
DECLARE #NodeName VARCHAR(100)
SET #NodeName = '/ROOT/Customer'
SELECT *
FROM OPENXML (#idoc, #NodeName,1)
WITH (CustomerID varchar(10),
ContactName varchar(20))
It could be that other versions of SQL only support the use of NVARCHAR as a parameter, not VARCHAR.
I hope this help.

How do I overcome OpenXML's 8000 character limit?

I'm loading an XML in SQL using OpenXML while declaring the variable the max i can go up to is 8000 chars :
DECLARE #xml_text varchar(8000)
Since text, ntext is not allowed to be used with openXML what other alternatives do i have to load the entire XML (over 20000 chars) in SQL ?
You should be able to use varchar(max) (SQL 2005 and higher)
DECLARE #idoc int
DECLARE #doc varchar(max)
SET #doc = '
<myxml>
<node nodeid="1" nodevalue="value 1">
</node>
</myxml>'
EXEC sp_xml_preparedocument #idoc OUTPUT, #doc
SELECT
*
FROM
OPENXML (#idoc, '/myxml/node',1) WITH ( nodeid varchar(10), nodevalue varchar(20) )
If you're using SQL 2005 or better you could use the XML data type itself. This way you would be able to avoid using OPENXML:
DECLARE #XDoc XML
SET #XDoc = '<Customer>
<FirstName>Fred</FirstName>
<LastName>Flinstone</LastName>
</Customer>
<Customer>
<FirstName>Barney</FirstName>
<LastName>Rubble</LastName>
</Customer>'
SELECT
Tbl.Col.value('FirstName[1]', 'VARCHAR(MAX)'),
Tbl.Col.value('LastName[1]', 'VARCHAR(MAX)')
FROM #XDoc.nodes('/Customer') Tbl(Col)