parsing xml with OpenXML - sql

I'm getting an error when executing this in SQL Server 2005, But works if I remove the namespaces from the root node :
DECLARE #XmlDocumentHandle int
DECLARE #XmlDocument nvarchar(1000)
SET #XmlDocument = N'<ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema>
<Customer>
<ID>VINET</ID>
<Name>Paul Henriot</Name>
<Order OrderID="10248" CustomerID="VINET" EmployeeID="5" OrderDate="1996-07-04T00:00:00">
<OrderDetail ProductID="11" Quantity="12"/>
<OrderDetail ProductID="42" Quantity="10"/>
</Order>
</Customer>
<Customer>
<ID>LILAS</ID>
<Name>Carlos Gonzlez</Name>
<Order OrderID="10283" CustomerID="LILAS" EmployeeID="3" OrderDate="1996-08-16T00:00:00">
<OrderDetail ProductID="72" Quantity="3"/>
</Order>
</Customer>
</ROOT>'
-- Create an internal representation of the XML document.
EXEC sp_xml_preparedocument #XmlDocumentHandle OUTPUT, #XmlDocument
-- Execute a SELECT statement using OPENXML rowset provider.
SELECT *
FROM OPENXML (#XmlDocumentHandle, '/ROOT/Customer',2)
WITH (CustomerID varchar(10) 'ID',
ContactName varchar(20) 'Name')
EXEC sp_xml_removedocument #XmlDocumentHandle

You are just missing a double quote at the end of the first line of xml:
SET #XmlDocument = N'<ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
(the 2nd-to-last char)
I am able to run your query ok on SQL 2008 after making this change.
John

Related

Fetch a value from xml in SQL Stored procedure

I tried to fetch an element from an XML in stored procedure as follows
USE [ION]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[AddToCustomer]
(#id VARCHAR(20))
AS
BEGIN
DECLARE #xx xml
DECLARE #custname varchar(8000)
DECLARE #fid varchar(20)
SET NOCOUNT ON;
SELECT #fid=[C_ID], #xx=cast([C_XML] as xml) FROM [ION].[dbo].[COR_INBOX_ENTRY] WHERE [C_WAS_PROCESSED]=0 and [C_ID]=#id
if(##ROWCOUNT!=0)
BEGIN
SELECT #xx.value('(/SyncMESCustomer/ApplicationArea/Sender/ConfirmationCode)[1]', 'varchar(100)')
END
END
I am pretty sure that the variable #xx is loaded with the xml. I need to select the value of '/SyncMESCustomer/ApplicationArea/Sender/ConfirmationCode' but its returning a NULL.
Sample xml is as follows
<SyncMESCustomer xmlns="http://schema.infor.com/InforOAGIS/2" xmlns:xs="http://www.w3.org/2001/XMLSchema" languageCode="GB" releaseID="9.2" systemEnvironmentCode="Production" versionID="2.9.1">
<ApplicationArea>
<Sender>
<LogicalID schemeVersionID="15.4.0.0">lid://infor.m3be.ipc_mec_dev</LogicalID>
<ComponentID schemeVersionID="MCP2-1514-02">M3BE</ComponentID>
<ConfirmationCode>OnError</ConfirmationCode>
</Sender>
<CreationDateTime>2017-06-09T13:41:36.996Z</CreationDateTime>
<BODID>5cfa6949-11ef-41dc-a380-4cc79f2687cc</BODID>
</ApplicationArea>
<DataArea>
<Sync>
<TenantID>TEST</TenantID>
<AccountingEntityID>1_001</AccountingEntityID>
<ActionCriteria>
<ActionExpression actionCode="Replace" />
</ActionCriteria>
</Sync>
<MESCustomer>
<CUSTOMER_NO>TEST6</CUSTOMER_NO>
<ipc_CSS_CUST_CUST_NAME>
<CUSTOMER_NO>TEST6</CUSTOMER_NO>
<CUST_NAME>Hawaii Inc_MES</CUST_NAME>
<STATUS_DATE>20170609</STATUS_DATE>
<STATUS_WORD>20</STATUS_WORD>
</ipc_CSS_CUST_CUST_NAME>
<STATUS_WORD>20</STATUS_WORD>
</MESCustomer>
</DataArea>
</SyncMESCustomer>
Thanks in advance.
;WITH XMLNAMESPACES(DEFAULT 'http://schema.infor.com/InforOAGIS/2','http://www.w3.org/2001/XMLSchema' as ns0)
Select #XML.value('SyncMESCustomer[1]/ApplicationArea[1]/Sender[1]/ConfirmationCode[1]','varchar(100)')
Returns
OnError
This works for me... you can add another alias to your namespace...
<SyncMESCustomer xmlns:xz="http://schema.infor.com/InforOAGIS/2" xmlns:xs="http://www.w3.org/2001/XMLSchema" languageCode="GB" releaseID="9.2" systemEnvironmentCode="Production" versionID="2.9.1"
DECLARE #xx XML
SET #xx = '<SyncMESCustomer>
<ApplicationArea>
<Sender>
<LogicalID schemeVersionID="15.4.0.0">lid://infor.m3be.ipc_mec_dev</LogicalID>
<ComponentID schemeVersionID="MCP2-1514-02">M3BE</ComponentID>
<ConfirmationCode>OnError</ConfirmationCode>
</Sender>
<CreationDateTime>2017-06-09T13:41:36.996Z</CreationDateTime>
<BODID>5cfa6949-11ef-41dc-a380-4cc79f2687cc</BODID>
</ApplicationArea>
<DataArea>
<Sync>
<TenantID>TEST</TenantID>
<AccountingEntityID>1_001</AccountingEntityID>
<ActionCriteria>
<ActionExpression actionCode="Replace" />
</ActionCriteria>
</Sync>
<MESCustomer>
<CUSTOMER_NO>TEST6</CUSTOMER_NO>
<ipc_CSS_CUST_CUST_NAME>
<CUSTOMER_NO>TEST6</CUSTOMER_NO>
<CUST_NAME>Hawaii Inc_MES</CUST_NAME>
<STATUS_DATE>20170609</STATUS_DATE>
<STATUS_WORD>20</STATUS_WORD>
</ipc_CSS_CUST_CUST_NAME>
<STATUS_WORD>20</STATUS_WORD>
</MESCustomer>
</DataArea>
</SyncMESCustomer>'
SELECT
xmlData.A.value('./ConfirmationCode[1]', 'varchar(100)')
FROM #xx.nodes('/SyncMESCustomer/ApplicationArea/Sender') xmlData(A);

Insert XML file into SQL Server

I'm trying to import an XML file into a SQL table. I found a few examples of code to do this, but I can't seem to get it to work. I've tried a few variations in my code but at this point I'm not sure if the issue is the XML file structure or my SQL.
Below is the code I'm using as well as the XML file (truncated to one record).
CREATE TABLE workspace.dbo.tbt_SED_XMLwithOpenXML
(
Id INT IDENTITY PRIMARY KEY,
XMLData XML,
LoadedDateTime DATETIME
)
INSERT INTO workspace.dbo.tbt_SED_XMLwithOpenXML(XMLData, LoadedDateTime)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE()
FROM OPENROWSET(BULK 'File.xml', SINGLE_BLOB) AS x;
DECLARE #XML AS XML, #hDoc AS INT, #SQL NVARCHAR (MAX)
SELECT #XML = XMLData FROM workspace.dbo.tbt_SED_XMLwithOpenXML WHERE ID = '1' -- The row to process
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML
INSERT INTO workspace.dbo.tb_SED_Emails
SELECT email
FROM OPENXML(#hDoc, 'responseData/manifest/contact_data')
WITH
(
email [varchar](128) 'email'
)
EXEC sp_xml_removedocument #hDoc
GO
XML File Example:
<?xml version="1.0" encoding="utf-8"?>
<methodResponse>
<item>
<methodName>
<![CDATA[]]>
</methodName>
<responseData>
<manifest>
<contact_data>
<email>jason.kang#stanfordalumni.org</email>
</contact_data>
</manifest>
</responseData>
<responseNum>
<![CDATA[1]]>
</responseNum>
<responseCode>
<![CDATA[]]>
</responseCode>
</item>
</methodResponse>
Try to use the built-in, native XQuery support instead of the clunky old OPENXML stuff:
SELECT
Email = XC.value('(email)[1]', 'varchar(255)')
FROM
workspace.dbo.tbt_SED_XMLwithOpenXML
CROSS APPLY
XMLData.nodes('/methodResponse/item/responseData/manifest/contact_data') AS XT(XC)
That should output the desired e-mail address for you:
You are using the wrong xPath expression.
Change 'responseData/manifest/contact_data' to 'methodResponse/item/responseData/manifest/contact_data'.

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

Xml to Database

I have an xml file as below:
<?xml version="1.0" encoding="UTF-8" ?>
- <DeliveryPackage xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VersionNo="Q214" CreationTime="2014-04-16T02:29:04.000000000" MapVersion="IND 14 2 00" Language_Code_Desc="../DEFINITIONS/language.xml" Country_Code_Desc="../DEFINITIONS/country.xml" Supplier_Code_Desc="../DEFINITIONS/supplier.xml" XY_Type="WGS84" Category_Code_Desc="../DEFINITIONS/category.xml" Char_Set="UTF-8" UpdateType="BulkUpdate" Coverage="IND" Category="7997">
- <POI>
<Action>Add</Action>
<SupplierID>3</SupplierID>
- <Identity>
<POI_Entity_ID>BEL_Q112FD_308076</POI_Entity_ID>
- <Names>
- <POI_Name Language_Code="ENG">
<Text>100 Raw Gym</Text>
</POI_Name>
</Names>
<Category_ID Type="NT">7997</Category_ID>
<Product_Type>23</Product_Type>
</Identity>
- <Locations>
- <Location>
- <Address>
- <ParsedAddress>
- <ParsedStreetAddress>
- <ParsedStreetName>
<StreetName Language_Code="ENG">NH-1</StreetName>
</ParsedStreetName>
</ParsedStreetAddress>
- <ParsedPlace>
<PlaceLevel2 Language_Code="ENG">Punjab</PlaceLevel2>
<PlaceLevel3 Language_Code="ENG">Amritsar</PlaceLevel3>
<PlaceLevel4 Language_Code="ENG">Amritsar</PlaceLevel4>
</ParsedPlace>
<CountryCode>IND</CountryCode>
</ParsedAddress>
</Address>
- <GeoPosition>
<Latitude>31.6294</Latitude>
<Longitude>74.81178</Longitude>
</GeoPosition>
- <MapLinkID>
<LinkID>1027669120</LinkID>
<Side_of_Street>R</Side_of_Street>
<Percent_from_RefNode>70</Percent_from_RefNode>
</MapLinkID>
- <Confidence>
<Match_Level>GeoPoint</Match_Level>
</Confidence>
</Location>
</Locations>
- <Contacts>
- <Contact Language_Code="ENG" Type="Main">
<Number Preferred="YES" Type="Phone Number">+(91)-9988692233</Number>
</Contact>
</Contacts>
</POI>
I want to insert all attributes in sql server table, starting from Action to Number.
I already tried on 1st three columns,like below:
At first I put complete xml file in a table 'data',then use the following code:
DECLARE #XML AS XML, #hDoc AS INT, #SQL NVARCHAR (MAX)
SELECT #XML = XMLData FROM data
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML
SELECT [Action],SupplierID,Poi_Entity_Id
FROM OPENXML(#hDoc, 'POI')
WITH
(
[Action] [varchar](50) '#Action',
SupplierID [int] '#SupplierID',
Poi_Entity_Id [varchar](100) 'Poi_Entity_Id'
)
EXEC sp_xml_removedocument #hDoc
GO
but getting null values in all columns...
I don't want to do it manually as I have 1000 records in my XML.
Please Help
Your data is stored in elements, not attributes, and you forgot to add DeliveryPackage node into the xpath:
select
T.C.value('Action[1]', 'nvarchar(128)') as [Action],
T.C.value('SupplierID[1]', 'nvarchar(128)') as SupplierID,
T.C.value('(Identity/POI_Entity_ID)[1]', 'nvarchar(128)') as POI_Entity_ID
from #XML.nodes('DeliveryPackage/POI') as T(C)
Or, if you want to use openxml:
declare #hDoc int
exec dbo.sp_xml_preparedocument #hDoc output, #XML
select
[Action],SupplierID,Poi_Entity_Id
from openxml(#hDoc, 'DeliveryPackage/POI')
with
(
[Action] [varchar](50) 'Action[1]',
SupplierID [int] 'SupplierID[1]',
Poi_Entity_Id [varchar](100) '(Identity/POI_Entity_ID)[1]'
)
exec dbo.sp_xml_removedocument #hDoc

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.