Cant read xml nodes from namespace - sql

Basically I have an XML file which resembles this:
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<Cube>
<Cube time="2018-06-15">
<Cube currency="USD" rate="1.2345"/>
<Cube currency="ZAR" rate="10.1"/>
</Cube>
<Cube time="2018-06-16">
<Cube currency="USD" rate="1.1596"/>
<Cube currency="ZAR" rate="9.546"/>
</Cube>
</Cube>
</gesmes:Envelope>
And I insert it like this:
INSERT INTO
fxRatesXml(xmlData, updatedOn)
SELECT
CONVERT(XML, bulkColumn),
GETDATE()
FROM
OPENROWSET(BULK 'I:\Downloads\eurofxref-hist-90d.xml', SINGLE_BLOB) as fxRateXmlData;
I then try to read the time, currency and rate like so:
DECLARE #xml AS XML, #hDoc AS INT, #sql NVARCHAR (MAX)
SELECT
#xml = xmlData
FROM
fxRatesXml
EXEC sp_xml_preparedocument #hDoc OUTPUT, #xml, '<root xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"/>'
SELECT
*
FROM
OPENXML(#hDoc, 'gesmes:Cube')
WITH
(
[time] nvarchar(max) 'Cube/time',
currency nvarchar(max) 'Cube/Cube/currency',
rate nvarchar(max) 'Cube/Cube/rate'
)
EXEC sp_xml_removedocument #hDoc
but no luck.
I am not sure where I'm going wrong any help would be appreciated.
UPDATED
Updated XML to be more specific. It can include more then just 2 cubes of time and more then 2 currencies per cube of time.
How would I iterate/select them all?

Once you have populated the #xml variable, instead of using EXEC sp_xml_preparedocument, try to define the namespaces you need using ;WITH XMLNAMESPACES:
I added the missing closing tag </gesmes:Envelope> at the end of the xml, so I tested my query with the following xml:
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<Cube>
<Cube time="2018-06-15">
<Cube currency="USD" rate="1.1596"/>
</Cube>
</Cube>
</gesmes:Envelope>
This is the query to retrieve tha data from xml variable #xml:
declare #xml xml = '<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> <Cube> <Cube time="2018-06-15"> <Cube currency="USD" rate="1.1596"/> </Cube> </Cube> </gesmes:Envelope>'
;WITH XMLNAMESPACES('http://www.gesmes.org/xml/2002-08-01' AS gesmes,
'http://www.ecb.int/vocabulary/2002-08-01/eurofxref' as ns)
SELECT
T.X.value('ns:Cube[1]/#currency','varchar(500)') AS [currency],
T.X.value('ns:Cube[1]/#rate','varchar(500)') AS [rate],
T.X.value('./#time','varchar(500)') AS [time]
FROM
#xml.nodes('/gesmes:Envelope/ns:Cube/ns:Cube') AS T(X)
Results:
To handle multiple <Cube> tags:
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<Cube>
<Cube time="2018-06-15">
<Cube currency="USD" rate="1.2345"/>
<Cube currency="ZAR" rate="10.1"/>
</Cube>
<Cube time="2018-06-16">
<Cube currency="USD" rate="1.1596"/>
<Cube currency="ZAR" rate="9.546"/>
</Cube>
</Cube>
</gesmes:Envelope>
you can use this query:
declare #xml xml ='<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> <Cube> <Cube time="2018-06-15"> <Cube currency="USD" rate="1.2345"/> <Cube currency="ZAR" rate="10.1"/> </Cube> <Cube time="2018-06-16"> <Cube currency="USD" rate="1.1596"/> <Cube currency="ZAR" rate="9.546"/> </Cube> </Cube> </gesmes:Envelope>'
;WITH XMLNAMESPACES('http://www.gesmes.org/xml/2002-08-01' AS gesmes,
'http://www.ecb.int/vocabulary/2002-08-01/eurofxref' as ns)
SELECT T.X.value('(.)[1]/#currency','varchar(500)') AS [currency]
,T.X.value('(.)[1]/#rate','varchar(500)') AS [rate]
,T.X.value('(..)[1]/#time','varchar(500)') AS [time]
FROM #xml.nodes('/gesmes:Envelope/ns:Cube/ns:Cube/ns:Cube') AS T(X)
Results:

Related

Extract information from XML to SQL Server temp table

I am working with some XML and I have an issue.
The xml looks like this:
<tagvalues>
<tagvalue>
<tag>Data.Barcode</tag>
<value>True</value>
</tagvalue>
<tagvalue>
<tag>Data.DateStampFirstScale</tag>
<value>20180111</value>
</tagvalue>
<tagvalue>
<tag>Data.DateStampLastScale</tag>
<value>20180111</value>
</tagvalue>
<tagvalue>
<tag>Data.Dot</tag>
<value>False</value>
</tagvalue>
<tagvalue>
<tag>Data.Hangtab</tag>
<value>False</value>
</tagvalue>
<tagvalue>
<tag>Data.Scale_x.Scale_0.Deviation</tag>
<value>0</value>
</tagvalue>
<tagvalue>
<tag>Data.Scale_x.Scale_0.DeviationHigh</tag>
<value>False</value>
</tagvalue>
<tagvalue>
<tag>Data.Scale_x.Scale_0.DeviationLimitHigh</tag>
<value>0</value>
</tagvalue>
</tagvalues>
and currently I'm getting the data with this code:
#data.value('/tagvalues[1]/tagvalue[3]/value[1]', 'nvarchar(100)')
The problem I'm having is that sometimes the order is changed, which means that I have to reconfigure it again.
Is it not possible to convert the XML text into an temp table like so:
Tag Value
--------------------------------------------------
Data.Barcode TRUE
Data.DateStampFirstScale 20180111
Data.DateStampLastScale 20180111
Data.Dot FALSE
Data.Hangtab FALSE
Data.Scale_x.Scale_0.Deviation 0
Data.Scale_x.Scale_0.DeviationHigh FALSE
Data.Scale_x.Scale_0.DeviationLimitHigh 0
Try the XQuery.. .nodes()
select n.value('tag[1]', 'varchar(max)') [Tag],
n.value('value[1]', 'varchar(max)') [Value]
from #xml.nodes('tagvalues/tagvalue') as p(n)
You mean like this?
DECLARE #XML xml;
SET #XML =
'<tagvalues>
<tagvalue>
<tag>Data.Barcode</tag>
<value>True</value>
</tagvalue>
<tagvalue>
<tag>Data.DateStampFirstScale</tag>
<value>20180111</value>
</tagvalue>
<tagvalue>
<tag>Data.DateStampLastScale</tag>
<value>20180111</value>
</tagvalue>
<tagvalue>
<tag>Data.Dot</tag>
<value>False</value>
</tagvalue>
<tagvalue>
<tag>Data.Hangtab</tag>
<value>False</value>
</tagvalue>
<tagvalue>
<tag>Data.Scale_x.Scale_0.Deviation</tag>
<value>0</value>
</tagvalue>
<tagvalue>
<tag>Data.Scale_x.Scale_0.DeviationHigh</tag>
<value>False</value>
</tagvalue>
<tagvalue>
<tag>Data.Scale_x.Scale_0.DeviationLimitHigh</tag>
<value>0</value>
</tagvalue>
</tagvalues>'
SELECT X.N.value('(tag/text())[1]','varchar(50)') AS Tag,
X.N.value('(value/text())[1]','varchar(50)') AS [Value]
FROM #XML.nodes('/tagvalues/tagvalue') X(N);

Parsing XML by OpenXML with multiple Parent nodes with multiple child nodes

I have the following XML:
<Report>
<Accounts>
<Account>
<Currency>USD</Currency>
<AccountBalance>45555</AccountBalance>
<Payments>
<PaymentData>
<PaymentCode>502</PaymentCode>
<PaymentAmount currCode="GBP">7000.00000000</PaymentAmount>
</PaymentData>
<PaymentData>
<PaymentCode>501</PaymentCode>
<PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
</PaymentData>
</Payments>
</Account>
<Account>
<Currency>USD</Currency>
<AccountBalance>50000</AccountBalance>
<Payments>
<PaymentData>
<PaymentCode>501</PaymentCode>
<PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
</PaymentData>
</Payments>
</Account>
</Accounts>
</Report>
My SQL Code is parsing this with the following code:
SELECT
[currCode] AS [Currency],
[AccountBalance] AS [AccountBalance],
[PaymentCode] AS [PaymentCode],
[PaymentCurrCode] AS [PaymentCurrCode],
[PaymentAmount] AS [PaymentAmount]
FROM OPENXML(#hDoc, 'Report/Accounts/Account',2)
WITH
(
[currCode] [nchar](3) 'currCode',
[AccountBalance] [decimal](18, 0) 'AccountBalance',
[PaymentCode] [nchar](10) 'Payments/PaymentData/PaymentCode',
[PaymentCurrCode] [nchar](3) 'Payments/PaymentData/PaymentAmount/#currCode',
[PaymentAmount] [decimal](18, 0) 'Payments/PaymentData/PaymentAmount'
)
I am getting the following result:
currCode | AccountBalance | PaymentCode | PaymentCurrCode | PaymentAmount
————————————————————————————————————————————————————————————————————————————————
USD | 45555 | 502 | GBP |7000.00000000
USD | 50000 | 501 | USD |5000.00000000
I am trying to get the multiple paymentdata and multiple account with the same openXml query. How Can is get all the data with the following result:
currCode | AccountBalance | PaymentCode | PaymentCurrCode | PaymentAmount
————————————————————————————————————————————————————————————————————————————————
USD | 45555 | 502 | GBP |7000.00000000
USD | 45555 | 501 | USD |5000.00000000
USD | 50000 | 501 | USD |5000.00000000
This is an up-to-date and state-of-the-art approach with XQuery/XPath methods. The result is the same, just faster and better to read:
DECLARE #XML XML=
'<Report>
<Accounts>
<Account>
<Currency>USD</Currency>
<AccountBalance>45555</AccountBalance>
<Payments>
<PaymentData>
<PaymentCode>502</PaymentCode>
<PaymentAmount currCode="GBP">7000.00000000</PaymentAmount>
</PaymentData>
<PaymentData>
<PaymentCode>501</PaymentCode>
<PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
</PaymentData>
</Payments>
</Account>
<Account>
<Currency>USD</Currency>
<AccountBalance>50000</AccountBalance>
<Payments>
<PaymentData>
<PaymentCode>501</PaymentCode>
<PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
</PaymentData>
</Payments>
</Account>
</Accounts>
</Report>';
SELECT Payment.value('(../../Currency)[1]','nchar(3)') AS currCode
,Payment.value('(../../AccountBalance)[1]','decimal(18,0)') AS AccountBalance
,Payment.value('PaymentCode[1]','nchar(10)') AS PaymentCode
,Payment.value('PaymentAmount[1]/#currCode','nchar(3)') AS PaymentCurrCode
,Payment.value('PaymentAmount[1]','decimal(18,0)') AS PaymentCurrCode
FROM #XML.nodes('Report/Accounts/Account/Payments/PaymentData') AS One(Payment)
This should work for you:
DECLARE #XML XML=
'<Report>
<Accounts>
<Account>
<Currency>USD</Currency>
<AccountBalance>45555</AccountBalance>
<Payments>
<PaymentData>
<PaymentCode>502</PaymentCode>
<PaymentAmount currCode="GBP">7000.00000000</PaymentAmount>
</PaymentData>
<PaymentData>
<PaymentCode>501</PaymentCode>
<PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
</PaymentData>
</Payments>
</Account>
<Account>
<Currency>USD</Currency>
<AccountBalance>50000</AccountBalance>
<Payments>
<PaymentData>
<PaymentCode>501</PaymentCode>
<PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
</PaymentData>
</Payments>
</Account>
</Accounts>
</Report>';
DECLARE #hDoc INT;
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML;
SELECT
[currCode] AS [Currency],
[AccountBalance] AS [AccountBalance],
[PaymentCode] AS [PaymentCode],
[PaymentCurrCode] AS [PaymentCurrCode],
[PaymentAmount] AS [PaymentAmount]
FROM OPENXML(#hDoc, 'Report/Accounts/Account/Payments/PaymentData',2)
WITH
(
[currCode] [nchar](3) '../../Currency',
[AccountBalance] [decimal](18, 0) '../../AccountBalance',
[PaymentCode] [nchar](10) 'PaymentCode',
[PaymentCurrCode] [nchar](3) 'PaymentAmount/#currCode',
[PaymentAmount] [decimal](18, 0) 'PaymentAmount'
)
EXEC sp_xml_removedocument #hDoc;

EXTRACT RESULTS FROM XML node with namespace using SQL

I Have the below XML and want to extract the values for the following Nodes
1. result
2. documentNumber
3. costElementCode
<commitmentsResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<result xmlns="http://response.cim.its.test.edu.au/">SUCCESS</result>
<value xmlns="http://finance.response.cim.its.test.edu.au/">
<documentNumber xmlns="http://finance.cim.its.test.edu.au/">12345</documentNumber>
<lineNumber>2</lineNumber>
<costElementCode>costElementCode</costElementCode>
<internalOrderNumber>1000002</internalOrderNumber>
<costCentreCode>9999</costCentreCode>
<wbsCode>3000</wbsCode>
<lineDescription>2 packets of pencils</lineDescription>
<accountNumber>100000</accountNumber>
<itemAmount>105.5</itemAmount>
<fundsDueDate>2015-06-15</fundsDueDate>
</commitmentLine>
<commitmentLine xmlns="http://finance.cim.its.test.edu.au/">
<lineNumber>2</lineNumber>
<costElementCode>costElementCode</costElementCode>
<internalOrderNumber>1000002</internalOrderNumber>
<costCentreCode>9999</costCentreCode>
<wbsCode>3000</wbsCode>
<lineDescription>2 packets of pencils</lineDescription>
<accountNumber>100000</accountNumber>
<itemAmount>105.5</itemAmount>
<fundsDueDate>2015-06-15</fundsDueDate>
</commitmentLine>
</value>
</commitmentsResponse>
Without using Namespaces:
DECLARE #myXML xml =
N'<commitmentsResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<result>SUCCESS</result>
<value>
<documentNumber>12345</documentNumber>
<commitmentLine>
<lineNumber>2</lineNumber>
<costElementCode>costElementCode</costElementCode>
<internalOrderNumber>1000002</internalOrderNumber>
<costCentreCode>9999</costCentreCode>
<wbsCode>3000</wbsCode>
<lineDescription>2 packets of pencils</lineDescription>
<accountNumber>100000</accountNumber>
<itemAmount>105.5</itemAmount>
<fundsDueDate>2015-06-15</fundsDueDate>
</commitmentLine>
<commitmentLine xmlns="http://finance.cim.its.test.edu.au/">
<lineNumber>2</lineNumber>
<costElementCode>costElementCode</costElementCode>
<internalOrderNumber>1000002</internalOrderNumber>
<costCentreCode>9999</costCentreCode>
<wbsCode>3000</wbsCode>
<lineDescription>2 packets of pencils</lineDescription>
<accountNumber>100000</accountNumber>
<itemAmount>105.5</itemAmount>
<fundsDueDate>2015-06-15</fundsDueDate>
</commitmentLine>
</value>
</commitmentsResponse>'
DECLARE #DocumentNumber INT
SELECT #DocumentNumber = [Table].[Column].value('documentNumber[1]', 'INT')
FROM #myXML.nodes('/commitmentsResponse/value') AS [Table]([Column])
DECLARE #Result VARCHAR(256)
SELECT #Result = [Table].[Column].value('result[1]', 'varchar(256)')
FROM #myXML.nodes('/commitmentsResponse') AS [Table]([Column])
DECLARE #CostElementCode VARCHAR(256)
SELECT #CostElementCode = [Table].[Column].value('costElementCode[1]', 'varchar(256)')
FROM #myXML.nodes('/commitmentsResponse/value/commitmentLine') AS [Table]([Column])
SELECT #Result
SELECT #DocumentNumber
SELECT #CostElementCode
With using namespaces:
DECLARE #myXML xml =
N'<commitmentsResponse xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<result xmlns="http://response.cim.its.test.edu.au/">SUCCESS</result>
<value>
<documentNumber xmlns="http://finance.cim.its.test.edu.au/">12345</documentNumber>
<commitmentLine>
<lineNumber>2</lineNumber>
<costElementCode>costElementCode</costElementCode>
<internalOrderNumber>1000002</internalOrderNumber>
<costCentreCode>9999</costCentreCode>
<wbsCode>3000</wbsCode>
<lineDescription>2 packets of pencils</lineDescription>
<accountNumber>100000</accountNumber>
<itemAmount>105.5</itemAmount>
<fundsDueDate>2015-06-15</fundsDueDate>
</commitmentLine>
<commitmentLine xmlns="http://finance.cim.its.test.edu.au/">
<lineNumber>2</lineNumber>
<costElementCode>costElementCode</costElementCode>
<internalOrderNumber>1000002</internalOrderNumber>
<costCentreCode>9999</costCentreCode>
<wbsCode>3000</wbsCode>
<lineDescription>2 packets of pencils</lineDescription>
<accountNumber>100000</accountNumber>
<itemAmount>105.5</itemAmount>
<fundsDueDate>2015-06-15</fundsDueDate>
</commitmentLine>
</value>
</commitmentsResponse>'
DECLARE #DocumentNumber INT
;WITH XMLNAMESPACES (N'http://finance.cim.its.test.edu.au/' as DYN)
SELECT #DocumentNumber = c.value('(DYN:documentNumber)[1]', 'INT')
FROM #myXML.nodes('/commitmentsResponse/value') t(c)
DECLARE #Result VARCHAR(256)
;WITH XMLNAMESPACES (N'http://response.cim.its.test.edu.au/' as DYN)
SELECT #Result = c.value('(DYN:result)[1]', 'VARCHAR(256)')
FROM #myXML.nodes('/commitmentsResponse') t(c)
DECLARE #CostElementCode VARCHAR(256)
SELECT #CostElementCode = c.value('(costElementCode)[1]', 'VARCHAR(256)')
FROM #myXML.nodes('/commitmentsResponse/value/commitmentLine') t(c)
SELECT #Result
SELECT #DocumentNumber
SELECT #CostElementCode

How can I save data from xml to sql 2008?

How can I save data from xml to sql 2008?
SQL table:
[dbo].[Position](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ImoNo] [numeric](8, 0) NOT NULL,
[sid] [numeric](5, 0) NULL,
[VesselName] [nvarchar](20) NULL,
[time] [datetime] NOT NULL,
[lat] [numeric](9, 2) NULL,
[lon] [numeric](9, 2) NULL,
[sog] [numeric](9, 2) NULL,
[cog] [numeric](9, 2) NULL,
[hdg] [numeric](9, 2) NULL,
[eta] [datetime] NULL,
[NextPort] [nvarchar](20) NULL)
XML file:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.fleettracker.de/api/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:GetPositionsResponse>
<body>
<result>Found 2 vessels.</result>
<success>true</success>
<shipsWithPositions xsi:type="ns1:FleettrackerShip">
<ns1:imono>9456159</ns1:imono>
<ns1:sid>780</ns1:sid>
<ns1:name>Trenta</ns1:name>
<ns1:charterShipName>Trenta</ns1:charterShipName>
<ns1:pasttrack>
<lat>1832900</lat>
<lon>7570400</lon>
<timestamp>2014-01-14T08:28:45Z</timestamp>
<orderNumber>0</orderNumber>
<sog>9.5</sog>
<cog>22</cog>
<hdg>22</hdg>
<eta>2014-01-15T12:00:00</eta>
<nextport>KWANGYANG</nextport>
</ns1:pasttrack>
<ns1:pasttrack>
<lat>1872560</lat>
<lon>7589000</lon>
<timestamp>2014-01-14T07:00:00Z</timestamp>
<orderNumber>1</orderNumber>
<sog>10.8</sog>
<cog>25</cog>
<hdg>25</hdg>
</ns1:pasttrack>
</shipsWithPositions>
<shipsWithPositions xsi:type="ns1:FleettrackerShip">
<ns1:imono>9144055</ns1:imono>
<ns1:sid>789</ns1:sid>
<ns1:name>Vipava</ns1:name>
<ns1:charterShipName>Vipava</ns1:charterShipName>
<ns1:pasttrack>
<lat>1757160</lat>
<lon>7536240</lon>
<timestamp>2014-01-13T19:00:00Z</timestamp>
<orderNumber>2</orderNumber>
<sog>9.4</sog>
<cog>21</cog>
<hdg>21</hdg>
</ns1:pasttrack>
<ns1:pasttrack>
<lat>1658200</lat>
<lon>7476480</lon>
<timestamp>2014-01-13T07:00:00Z</timestamp>
<orderNumber>3</orderNumber>
<sog>8.4</sog>
<cog>29</cog>
<hdg>29</hdg>
</ns1:pasttrack>
<ns1:pasttrack>
<lat>1630000</lat>
<lon>7455400</lon>
<timestamp>2014-01-13T03:00:03Z</timestamp>
<orderNumber>4</orderNumber>
<sog>8.83</sog>
<cog>34</cog>
<hdg>34</hdg>
<eta>2014-01-15T08:00:00</eta>
<nextport>KWANGYANG</nextport>
</ns1:pasttrack>
</shipsWithPositions>
</body>
</ns1:GetPositionsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I tried with this query, but I get error msg
'XQuery [nodes()]: The names "SOAP-ENV" and "ns1:" do not denote a namespace.'
DECLARE #xml XML
DECLARE #character VARCHAR(MAX)
SELECT #character = x.y
FROM OPENROWSET( BULK 'C:\Users\Nale\Desktop\POS.xml', SINGLE_CLOB ) x(y)
-- Fix up the ampersand
SELECT #xml = REPLACE( #character, '&', '&' )
-- Get the tally information
SELECT
x.y.value('ns1:imono/text())[1]', 'NUMERIC (8,0)') ImoNo,
x.y.value('ns1:sid/text())[1]', 'NUMERIC (5,0)') sid,
x.y.value('ns1:VesselName/text())[1]', 'NVARCHAR (20)') VesselName,
x.y.value('ns1:pasttrack/time/text())[1]', 'DATETIME') time,
x.y.value('ns1:pasttrack/lat/text())[1]', 'NUMERIC (9,2)') lat,
x.y.value('ns1:pasttrack/lon/text())[1]', 'NUMERIC (9,2)') lon,
x.y.value('ns1:pasttrack/sog/text())[1]', 'NUMERIC (9,2)') sog,
x.y.value('ns1:pasttrack/cog/text())[1]', 'NUMERIC (9,2)') cog,
x.y.value('ns1:pasttrack/hdg/text())[1]', 'NUMERIC (9,2)') hdg,
x.y.value('ns1:pasttrack/eta/text())[1]', 'DATETIME') eta,
x.y.value('ns1:pasttrack/NextPort/text())[1]', 'NVARCHAR (20)') NextPort
FROM #xml.nodes('SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:GetPositionsResponse/body/shipsWithPositions') AS x(y)
XML file is on local disk.
Will I use some sql query, or what is the best way to save data from xml to sql table?
Make XML valid
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.fleettracker.de/api/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ns1:GetPositionsResponse>
<body>
<result>Found 2 vessels.</result>
<success>true</success>
<shipsWithPositions xsi:type="ns1:FleettrackerShip">
<ns1:imono>9456159</ns1:imono>
<ns1:sid>780</ns1:sid>
<ns1:name>Trenta</ns1:name>
<ns1:charterShipName>Trenta</ns1:charterShipName>
<ns1:pasttrack>
<lat>1832900</lat>
<lon>7570400</lon>
<timestamp>2014-01-14T08:28:45Z</timestamp>
<orderNumber>0</orderNumber>
<sog>9.5</sog>
<cog>22</cog>
<hdg>22</hdg>
<eta>2014-01-15T12:00:00</eta>
<nextport>KWANGYANG</nextport>
</ns1:pasttrack>
<ns1:pasttrack>
<lat>1872560</lat>
<lon>7589000</lon>
<timestamp>2014-01-14T07:00:00Z</timestamp>
<orderNumber>1</orderNumber>
<sog>10.8</sog>
<cog>25</cog>
<hdg>25</hdg>
</ns1:pasttrack>
</shipsWithPositions>
<shipsWithPositions xsi:type="ns1:FleettrackerShip">
<ns1:imono>9144055</ns1:imono>
<ns1:sid>789</ns1:sid>
<ns1:name>Vipava</ns1:name>
<ns1:charterShipName>Vipava</ns1:charterShipName>
<ns1:pasttrack>
<lat>1757160</lat>
<lon>7536240</lon>
<timestamp>2014-01-13T19:00:00Z</timestamp>
<orderNumber>2</orderNumber>
<sog>9.4</sog>
<cog>21</cog>
<hdg>21</hdg>
</ns1:pasttrack>
<ns1:pasttrack>
<lat>1658200</lat>
<lon>7476480</lon>
<timestamp>2014-01-13T07:00:00Z</timestamp>
<orderNumber>3</orderNumber>
<sog>8.4</sog>
<cog>29</cog>
<hdg>29</hdg>
</ns1:pasttrack>
<ns1:pasttrack>
<lat>1630000</lat>
<lon>7455400</lon>
<timestamp>2014-01-13T03:00:03Z</timestamp>
<orderNumber>4</orderNumber>
<sog>8.83</sog>
<cog>34</cog>
<hdg>34</hdg>
<eta>2014-01-15T08:00:00</eta>
<nextport>KWANGYANG</nextport>
</ns1:pasttrack>
</shipsWithPositions>
</body>
</ns1:GetPositionsResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
2. Add namespaces to your query
DECLARE #xml XML
DECLARE #character VARCHAR(MAX)
SELECT #xml = x.y
FROM OPENROWSET( BULK 'C:\Users\Nale\Desktop\POS.xml', SINGLE_CLOB ) x(y)
-- Get the tally information
;WITH XMLNAMESPACES (
'http://www.fleettracker.de/api/1.0' as ns1,
'http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://schemas.xmlsoap.org/soap/envelope/' AS e
)
SELECT
x.y.value('(ns1:imono/text())[1]', 'NUMERIC (8,0)') ImoNo,
x.y.value('(ns1:sid/text())[1]', 'NUMERIC (5,0)') sid,
x.y.value('(ns1:VesselName/text())[1]', 'NVARCHAR (20)') VesselName,
x.y.value('(ns1:pasttrack/time/text())[1]', 'DATETIME') time,
x.y.value('(ns1:pasttrack/lat/text())[1]', 'NUMERIC (9,2)') lat,
x.y.value('(ns1:pasttrack/lon/text())[1]', 'NUMERIC (9,2)') lon,
x.y.value('(ns1:pasttrack/sog/text())[1]', 'NUMERIC (9,2)') sog,
x.y.value('(ns1:pasttrack/cog/text())[1]', 'NUMERIC (9,2)') cog,
x.y.value('(ns1:pasttrack/hdg/text())[1]', 'NUMERIC (9,2)') hdg,
x.y.value('(ns1:pasttrack/eta/text())[1]', 'DATETIME') eta,
x.y.value('(ns1:pasttrack/NextPort/text())[1]', 'NVARCHAR (20)') NextPort
FROM #xml.nodes('e:Envelope/e:Body/ns1:GetPositionsResponse/body/shipsWithPositions') AS x(y)

Get all the Subchild values using XQUERY-SQL

I'm attempting to create an xquery expression that will return all the subchild node values. Now I get only the first subchild under each child.
I have the following XML:
<order>
<child1>
<subchild id="S1">
<name type="primary">
<first>NAOMI</first>
<middle />
<last>ADAMS</last>
<suffix />
</name>
</subchild>
<subchild id="S2">
<name type="primary">
<first>TOVER</first>
<middle />
<last>DALI</last>
<suffix />
</name>
</subchild>
</child1>
<child2>
<subchild id="V1">
<year>2002</year>
<make>PONTI</make>
<model>AZTEK</model>
<vin>3G7DA03E32S597676</vin>
</subchild>
<subchild id="V2">
<year>2003</year>
<make>HONDA</make>
<model>CIVIC</model>
<vin>2H94DA03E80S1538</vin>
</subchild>
</child2>
<child3>
<subchild id="A1">
<house>7741</house>
<street1>SAINT BERNARD ST</street1>
<apartment />
<city>PLAYA DEL REY</city>
<state>CA</state>
<postalcode>90293</postalcode>
</subchild>
<subchild id="A2">
<house>2371</house>
<street1>HANNUM DR</street1>
<apartment />
<city>MARINA DEL REY</city>
<state>CA</state>
<postalcode>90293</postalcode>
</subchild>
</child3>
</order>
My result should look like :
FirstName LastName HouseNumber StreetName City SState Zip Year Model Make VIN
NAOMI ADAMS 7741 SAINT BERNARD ST PLAYA DEL REY CA 90293 2002 PONTI AZTEK G7DA03E32S597676
TOVER DALI 2371 HANNUM DR MARINA DEL REY CA 90024 2003 HONDA CIVIC 2H94DA03E80S1538
My query :
SELECT
FirstName, LastName, HouseNumber, StreetName, City, SState, Zip, Year, Model, Make, VIN
FROM
xmlTable
OUTER APPLY
(
SELECT
tbl.col.value('(child1/subchild/name/first)[1]','varchar(20)') AS FirstName,
tbl.col.value('(child1/subchild/name/last)[1]','varchar(20)') AS LastName,
tbl.col.value('(child1/subchild/name/middle)[1]','varchar(20)') AS MiddleName,
tbl.col.value('(child3/subchild/house)[1]','varchar(20)') AS HouseNumber,
tbl.col.value('(child3/subchild/street1)[1]','varchar(20)') AS StreetName,
tbl.col.value('(child3/subchild/city)[1]','varchar(20)') AS City,
tbl.col.value('(child3/subchild/state)[1]','varchar(20)') AS SState,
tbl.col.value('(child3/subchild/postalcode)[1]','varchar(20)') AS Zip,
tbl.col.value('(child2/subchild/model_year)[1]','varchar(20)') AS Year,
tbl.col.value('(child2/subchild/model)[1]','varchar(20)') AS Model,
tbl.col.value('(child2/subchild/make)[1]','varchar(20)') AS Make,
tbl.col.value('(child2/subchild/vin)[1]','varchar(20)') AS VIN
FROM
xmldocument.nodes('//order') AS tbl(col)
) Y
Thanks
DECLARE #x XML
SELECT #x = 'Your XML here'
SELECT
tbl.col.value('(child1/subchild/name/first)[position() = sql:column("s.number")][1]','varchar(20)') AS FirstName,
tbl.col.value('(child1/subchild/name/last)[position() = sql:column("s.number")][1]', 'varchar(20)') AS LastName,
tbl.col.value('(child1/subchild/name/middle)[position() = sql:column("s.number")][1]', 'varchar(20)') AS MiddleName,
tbl.col.value('(child3/subchild/house)[position() = sql:column("s.number")][1]', 'varchar(20)') AS HouseNumber,
tbl.col.value('(child3/subchild/street1)[position() = sql:column("s.number")][1]', 'varchar(20)') AS StreetName,
tbl.col.value('(child3/subchild/city)[position() = sql:column("s.number")][1]', 'varchar(20)') AS City,
tbl.col.value('(child3/subchild/state)[position() = sql:column("s.number")][1]', 'varchar(20)') AS SState,
tbl.col.value('(child3/subchild/postalcode)[position() = sql:column("s.number")][1]', varchar(20)') AS Zip,
tbl.col.value('(child2/subchild/model_year)[position() = sql:column("s.number")][1]', 'varchar(20)') AS Year,
tbl.col.value('(child2/subchild/model)[position() = sql:column("s.number")][1]', 'varchar(20)') AS Model,
tbl.col.value('(child2/subchild/make)[position() = sql:column("s.number")][1]', 'varchar(20)') AS Make,
tbl.col.value('(child2/subchild/vin)[position() = sql:column("s.number")][1]', 'varchar(20)') AS VIN
FROM #x.nodes('/order') AS tbl(col)
CROSS JOIN master..spt_values s
WHERE type = 'P' AND number BETWEEN 1
AND col.query('count(child1/subchild)').value('.', 'INT')