Problem with parsing XML with multiple namespace into SQL - 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;

Related

how to read this xml in sql server

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

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.

How can I to read a XML from a URL using T-SQL?

Have xml file in url :
<response>
<sum>0</sum>
<result>0</result>
<comment>sel*1.9488|buy*1.9453</comment>
</response>
Now want stored procedure where i can parse this xml file from url and update into columns values which is in <comment>sel*1.9488|buy*1.9453</comment> want add buy*1.9453 to my table. How do it ?
To get the XML from a URL you need to do the following:
Enable Ole Automation Procedures
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ole Automation Procedures', 1;
GO
RECONFIGURE;
GO
Then to get the XML from a url, (answer based on an updated version from here), the following creates a temp table to store the value so you can then process the results using an xpath and substring.
This is a working example using a google maps xml, you will need to update the url and xpath to your specific requirements.
USE tempdb
GO
IF OBJECT_ID('tempdb..#xml') IS NOT NULL DROP TABLE #xml
CREATE TABLE #xml ( yourXML XML )
GO
DECLARE #URL VARCHAR(8000)
DECLARE #QS varchar(50)
-- & or ? depending if there are other query strings
-- Use this for when there is other query strings:
SELECT #QS = '&date='+convert(varchar(25),getdate(),126)
-- Use this for when there is NO other query strings:
-- SELECT #QS = '?date='+convert(varchar(25),getdate(),126)
SELECT #URL = 'http://maps.google.com/maps/api/geocode/xml?latlng=10.247087,-65.598409&sensor=false' + #QS
DECLARE #Response varchar(8000)
DECLARE #XML xml
DECLARE #Obj int
DECLARE #Result int
DECLARE #HTTPStatus int
DECLARE #ErrorMsg varchar(MAX)
EXEC #Result = sp_OACreate 'MSXML2.XMLHttp', #Obj OUT
EXEC #Result = sp_OAMethod #Obj, 'open', NULL, 'GET', #URL, false
EXEC #Result = sp_OAMethod #Obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
EXEC #Result = sp_OAMethod #Obj, send, NULL, ''
EXEC #Result = sp_OAGetProperty #Obj, 'status', #HTTPStatus OUT
INSERT #xml ( yourXML )
EXEC #Result = sp_OAGetProperty #Obj, 'responseXML.xml'--, #Response OUT
SELECT yourXML.value('(//GeocodeResponse/status)[1]','VARCHAR(MAX)') from #xml
In order to insert the substring you will need to do something like this to return everything after the pipe and add into your table:
INSERT tableDestination (valueDestination)
SELECT substring(yourXML.value('(//response/comment)[1]','VARCHAR(MAX)'),charindex('|',yourXML.value('(//response/comment)[1]','VARCHAR(MAX)'),1)+1,len(yourXML.value('(//response/comment)','VARCHAR(MAX)'))) from #xml
How about somethine like
DECLARE #xml XML =
'<response>
<sum>0</sum>
<result>0</result>
<comment>sel*1.9488|buy*1.9453</comment>
</response>'
SELECT #xml.value('(//response/comment)[1]','VARCHAR(MAX)')
From value() Method (xml Data Type)
Performs an XQuery against the XML and returns a value of SQL type.
This method returns a scalar value.
You typically use this method to extract a value from an XML instance
stored in an xml type column, parameter, or variable. In this way, you
can specify SELECT queries that combine or compare XML data with data
in non-XML columns.
SQL Fiddle DEMO

Saving data in table using OpenXML

i want to save xml data into a table in sp,passed as string,here is my code
alter PROCEDURE usp_be_insertXML
-- Add the parameters for the stored procedure here
#xml varchar(1000)
AS
BEGIN
DECLARE #idoc int
DECLARE #doc varchar(1000)
SET NOCOUNT ON;
EXEC sp_xml_preparedocument #idoc OUTPUT, #xml
BEGIN TRY
INSERT INTO testing ([Name] ,[Fname] )
SELECT Column1,Column2
FROM OPENXML (#idoc, 'NewDataSet/Sheet1', 1)
WITH ([Column1] [nvarchar](50),
[Column2] [nvarchar](50))
END TRY
BEGIN CATCH
END CATCH
EXECUTE sp_xml_removedocument #idoc
END
This inserts NULL only in table,any help?
and here is XML
<NewDataSet>
<Sheet1>
<Column1>Name</Column1>
<Column2>Fname</Column2>
</Sheet1>
<Sheet1>
<Column1>khan</Column1>
<Column2>dd</Column2>
</Sheet1>
<Sheet1>
<Column1>mytest</Column1>
<Column2>ff</Column2>
</Sheet1>
</NewDataSet>
Problem is you're specifying to use an "attribute-centric" mapping (the "1" in the last parameter of OPENXML), but your data elements are actually elements. You can get your desired result one of two ways:
1) Change the parameter to "2"
2) Change your WITH clause to explicitly state the child element you're looking for:
WITH (
[Column1] [nvarchar](50) 'Column1'
, [Column2] [nvarchar](50) 'Column2'
)

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)