SQL to Parse XML - sql-server

Can someone please help... I cannot seem to figure this out... I need to parse this using T-SQL. I have it saved as a file in the C:\Temp directory, named "OpenPos.XML". Any help would be very greatly appreciated. I need to be able to parse the XML and write it to a SQL table.
If I do an outer apply at all levels, it applies every PO # to every line instead of just for the lines related to that PO #.
XML File:
<?xml version="1.0" encoding="utf-8"?>
<acXML lang="en-us" xmlns="https://www.autocrib.net/acXMLSchema.xsd">
<Header>
<From>
<Company>Rolls Royce ATC (Indianapolis)</Company>
<Identity>rollsroyceatc-indianapolis</Identity>
<DatabaseName>AutoCribNet2</DatabaseName>
</From>
</Header>
<Request>
<OpenPurchaseOrderRequest ReqType="GET">
<PoNo>1716W</PoNo>
<ExternalPoNo />
<LineItems>
<Item>
<Line>1</Line>
<TagNo>1716</TagNo>
<VendorID>QMS</VendorID>
<ItemID>CARD BC6266</ItemID>
<ItemType>Expendable</ItemType>
<ItemRFID />
<Station>01</Station>
<Bin>0825-04-B-06</Bin>
<OrderQty>1</OrderQty>
<Received>1</Received>
<ReceivedBurn>0</ReceivedBurn>
<PackQty>1</PackQty>
<UnitCost>0.0000</UnitCost>
<UnitPrice>0.0000</UnitPrice>
<Lot />
<IsSpotBuy>False</IsSpotBuy>
<SpotTranCode>0</SpotTranCode>
<Inspect>False</Inspect>
<InspDate />
<InspOnHand>0</InspOnHand>
<InspBurn>0</InspBurn>
<OrderDate>01-13-2022</OrderDate>
<DueDate>01-25-2022</DueDate>
<PromiseDt>01-25-2022</PromiseDt>
<ReceiveDt />
<Department />
<Job />
<Machine />
<Reason />
<Part />
<Processed>False</Processed>
</Item>
</LineItems>
</OpenPurchaseOrderRequest>
<OpenPurchaseOrderRequest ReqType="GET">
SQL:
--Open POs
SELECT PO_X = CAST(BulkColumn AS xml)
INTO #PO
FROM OPENROWSET(BULK 'C:\AutoCrib WebServices\XML Files\ATC\OpenPOs.XML', SINGLE_CLOB) t
SELECT [Company] = p.PO_X.value('(//*:Header/*:From/*:Company)[1]', 'varchar(150)')
, [Identity] = f.value('(*:Identity)[1]', 'varchar(200)')
, [DatabaseNM] = f.value('(*:DatabaseName)[1]', 'varchar(50)')
, [PoNo] = r.value('(*:PoNo)[1]', 'varchar(10)')
, [ItemLine] = i.value('(*:Line)[1]', 'int')
, [ItemTagNo] = i.value('(*:TagNo)[1]', 'varchar(10)')
, [ItemVendorID] = i.value('(*:VendorID)[1]', 'varchar(100)')
, [ItemID] = i.value('(*:ItemID)[1]', 'varchar(30)')
, [ItemRFID] = i.value('(*:ItemRFID)[1]', 'varchar(50)')
, [ItemStation] = i.value('(*:Station)[1]', 'varchar(5)')
, [ItemBin] = i.value('(*:Bin)[1]', 'varchar(30)')
, [ItemOrderQty] = i.value('(*:OrderQty)[1]', 'int')
, [ItemReceived] = i.value('(*:Received)[1]', 'int')
, [ItemReceivedBurn] = i.value('(*:ReceivedBurn)[1]', 'int')
, [ItemPackQty] = i.value('(*:PackQty)[1]', 'int')
, [ItemUnitCost] = i.value('(*:UnitCost)[1]', 'money')
, [ItemUnitPrice] = i.value('(*:UnitPrice)[1]', 'money')
, [ItemOrderDate] = i.value('(*:OrderDate)[1]', 'datetime')
, [ItemDueDate] = i.value('(*:DueDate)[1]', 'datetime')
, [ItemPromiseDate] = i.value('(*:PromiseDt)[1]', 'datetime')
, [ItemReceiveDate] = i.value('(*:ReceiveDt)[1]', 'datetime')
, [ItemProcessed] = i.value('(*:Processed)[1]', 'varchar(10)')
FROM #PO p
OUTER APPLY p.PO_X.nodes('//*:Header/*:From') a(f)
OUTER APPLY p.PO_X.nodes('//*:Request/*:OpenPurchaseOrderRequest') c(r)
OUTER APPLY p.PO_X.nodes('//*:Request/*:OpenPurchaseOrderRequest/*:LineItems/*:Item') l(i)
DROP TABLE #PO

Start with loading the file. This uses OPENROWSET, but you might find BULK INSERT more flexible.
SELECT DepX = CAST(BulkColumn AS xml)
INTO #Departments
FROM OPENROWSET(BULK 'C:\Temp\Departments.XML', SINGLE_CLOB) t
--SINGLE_CLOB|SINGLE_NCLOB for Ascii vs Unicode
Now, we can query the xml
SELECT [From.Company] = d.DepX.value('(//*:Header/*:From/*:Company)[1]', 'varchar(99)')
/* Shorter paths if we OUTER APPLY the root we're interested in */
, [From.Company Shortcut] = f.value('(*:Company)[1]', 'varchar(99)')
FROM #Departments d
OUTER APPLY d.DepX.nodes('//*:Header/*:From') a(f)
Results
From.Company
From.Company Shortcut
Test Company (Indianapolis)
Test Company (Indianapolis)
For help with xml shredding, try Jacob Sebastian's SELECT * FROM XML
The output is helpful, but taking the time to go through and understand how it works is very educational.
This uses namespace wildcard *:
More complex xml might require WITH XMLNAMESPACE

I was finally able to figure it out. I was missing the namespace. Here's my SQL logic:
DECLARE #XML XML =
(SELECT *
FROM OPENROWSET(BULK 'C:\Temp\OpenPOs.XML', SINGLE_CLOB) t)
;WITH XMLNAMESPACES (DEFAULT 'https://www.autocrib.net/acXMLSchema.xsd')
SELECT A.evnt.value('(PoNo/text())[1]','varchar(10)') AS Event_DriverId
,B.rec.value('(Line/text())[1]','int') AS Record_RecordId
FROM #XML.nodes('/acXML/Request/OpenPurchaseOrderRequest') A(evnt)
OUTER APPLY A.evnt.nodes('LineItems/Item') B(rec);

Related

XML output in SQL help needed

Hi I have the following code in SQL that outputs xml between 2 tables. The output is 90% correct but if possible add to the output and then also remove some of the output text.
I am not sure if SQL has the ability to code a type of a element in the output. Please see the code below with the output. Currently if possible I would like to make 2 changes to my current output. The changes are list at the end of the port
DECLARE #ID_Rechnung int = 1978,
#XMLData xml;
WITH XMLNAMESPACES ('?xml version="1.0" encoding="UTF-8"?' as ext)
SELECT
#XMLData = xmldat.xmldataCol
FROM
(
SELECT (
SELECT
-- HIER XML Daten generieren
[InvoiceHeader].[InvoiceDate] AS 'invoice-date',
([InvoiceHeader].[InvoiceNumber]) AS 'invoice-number',
cast(replace([InvoiceHeader].[GrossValue],' ','') as decimal(18,2)) AS 'gross-total',
cast(replace([InvoiceHeader].[NetValue],' ','') as decimal(18,2)) AS 'amount-due',
[InvoiceHeader].[VatRate] AS 'tax-rate',
cast(replace([InvoiceHeader].[VatValue],' ','') as decimal(18,2)) AS 'tax-amount',
[ImagePath] AS 'image-scan-url',
[InvoiceType] AS 'document-type',
[LegalEntityVATNo] AS 'account-type/id',
[LegalEntityName] AS 'account-type/name',
[SupplierCode] as 'supplier/number',
[Currency] as 'currency/code',
(
SELECT rtrim([InvoiceLines].[LineNumber]) AS [order-line-num]
, [PONumber] as [po-number],
CAST([InvoiceLines].[UnitPrice] AS decimal(18,2)) AS Price ,
[Quantity] as quantity,
[TaxAmount] as [tax-amount],
[LineTotal] as [total],
[Decsription] as description
FROM [InvoiceLines] WHERE [InvoiceLines].[DOCID] = #id_Rechnung
FOR XML PATH('Invoice-line'), ROOT('invoice-lines'), TYPE
)
FROM [InvoiceHeader]
WHERE [InvoiceHeader].[DOCID] = #ID_Rechnung
FOR XML PATH(''), TYPE, ROOT('invoice-header')
) AS xmldataCol
) AS xmldat;
SELECT #XMLData
.query('<invoice-header>
{
for $x in /invoice-header/*[local-name()!="root"]
return $x,
for $x in /invoice-header/root/r
return <invoice-lines>/<invoice-line>{$x/*}</invoice-line></invoice-lines>
}
</invoice-header>');
Output:
<invoice-header>
<invoice-date>20180509</invoice-date>
<invoice-number>1075440</invoice-number>
<gross-total>1376.67</gross-total>
<amount-due>1197.10</amount-due>
<tax-rate>15.00%</tax-rate>
<tax-amount>179.57</tax-amount>
<image-scan-url>\\INTEL-SQL01\Attachment\2018-06-20\7e0dd165-81d6-445a-95d1-8aac686d44ed\f9a1179c-2a54-480e-b97a-ce6ac7327ae0.000</image-scan-url>
<account-type>
<id>4010112052</id>
<name>CONSOLIDATEDPOWERPROJECTS</name>
</account-type>
<supplier>
<number>12345</number>
</supplier>
<currency>
<code>ZAR</code>
</currency>
<invoice-lines xmlns:ext="?xml version="1.0" encoding="UTF-8"?">
<Invoice-line>
<order-line-num>4</order-line-num>
<po-number>120934861</po-number>
<Price>50.00</Price>
<quantity>1.000000</quantity>
<tax-amount>7.500000</tax-amount>
<total>50.00</total>
<description>Test1</description>
</Invoice-line>
<Invoice-line>
<order-line-num>2</order-line-num>
<po-number>120934861</po-number>
<Price>10.00</Price>
<quantity>2.000000</quantity>
<tax-amount>4.500000</tax-amount>
<total>20.00</total>
<description>Test2</description>
</Invoice-line>
</invoice-lines>
</invoice-header>
1.How do I get rid of the following xmlns:ext="?xml version="1.0" encoding="UTF-8&in the line: "<invoice-lines xmlns:ext="?xml version="1.0" encoding="UTF-8"?">"
How would I code "<tax-amount>7.500000</tax-amount> to get the output": "<tax-amount type="decimal">7.500000</tax-amount>"
Without a minimal reproducible example it is not possible to give you a full working answer.
(1) As #JeroenMostert already pointed out, the
'?xml version="1.0" encoding="UTF-8"?'
is an XML prolog declaration. Just delete the following line:
WITH XMLNAMESPACES ('?xml version="1.0" encoding="UTF-8"?' as ext)
(2) Here is a conceptual example how to add an attribute to an XML element. What is important here is a sequential order of adding, i.e. attribute shall be first, element itself is 2nd.
SQL
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, [tax-amount] VARCHAR(20));
INSERT INTO #tbl ([tax-amount]) VALUES
(N'7.500000'),
(N'18.000000');
SELECT
'decimal' AS [tax-amount/#type]
, [tax-amount]
FROM #tbl
FOR XML PATH('r'), TYPE, ROOT('root');
Output
<root>
<r>
<tax-amount type="decimal">7.500000</tax-amount>
</r>
<r>
<tax-amount type="decimal">18.000000</tax-amount>
</r>
</root>

sql server query xml related nodes

In the T-SQL sample code below I am trying to query related pieces of data that are in different nodes in the xml, but I can't figure out how to do that. For example, the LX01_AssignedNumber and the C00302_ProcedureCode values need to be pulled together for the same record. The result should look like this.
CLAIM_SOURCE_ID ITEM_NUMBER HCPCS_LINE_CODE
16202E123456 1 99203
16202E123456 2 96372
Can someone help me?
USE [tempdb];
GO
DECLARE #XML XML =
N'<ns1:X12EnrichedMessage xmlns:ns1="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/EnrichedMessageXML">
<TransactionSet>
<!-- ProcessLogID=PLG0007182226 ;ProcessLogDetailID=PLG0007182968 ;EnvID=1;RetryCount=1 -->
<ns0:X12_00501_837_P xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<ns0:TS837_2000A_Loop xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<ns0:TS837_2000B_Loop xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<ns0:TS837_2300_Loop xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
<ns0:TS837_2400_Loop>
<ns0:LX_ServiceLineNumber>
<LX01_AssignedNumber>1</LX01_AssignedNumber>
</ns0:LX_ServiceLineNumber>
<ns0:SV1_ProfessionalService>
<ns0:C003_CompositeMedicalProcedureIdentifier>
<C00301_ProductorServiceIDQualifier>HC</C00301_ProductorServiceIDQualifier>
<C00302_ProcedureCode>99203</C00302_ProcedureCode>
<C00303_ProcedureModifier>25</C00303_ProcedureModifier>
<C00307_Description>NO DESCRIPTION</C00307_Description>
</ns0:C003_CompositeMedicalProcedureIdentifier>
<SV102_LineItemChargeAmount>167.82</SV102_LineItemChargeAmount>
<SV103_UnitorBasisforMeasurementCode>UN</SV103_UnitorBasisforMeasurementCode>
<SV104_ServiceUnitCount>1</SV104_ServiceUnitCount>
<ns0:C004_CompositeDiagnosisCodePointer>
<C00401_DiagnosisCodePointer>1</C00401_DiagnosisCodePointer>
</ns0:C004_CompositeDiagnosisCodePointer>
</ns0:SV1_ProfessionalService>
<ns0:DTP_SubLoop_2>
<ns0:DTP_Date_ServiceDate>
<DTP01_DateTimeQualifier>472</DTP01_DateTimeQualifier>
<DTP02_DateTimePeriodFormatQualifier>RD8</DTP02_DateTimePeriodFormatQualifier>
<DTP03_ServiceDate>20160627-20160627</DTP03_ServiceDate>
</ns0:DTP_Date_ServiceDate>
</ns0:DTP_SubLoop_2>
</ns0:TS837_2400_Loop>
<ns0:TS837_2400_Loop>
<ns0:LX_ServiceLineNumber>
<LX01_AssignedNumber>2</LX01_AssignedNumber>
</ns0:LX_ServiceLineNumber>
<ns0:SV1_ProfessionalService>
<ns0:C003_CompositeMedicalProcedureIdentifier>
<C00301_ProductorServiceIDQualifier>HC</C00301_ProductorServiceIDQualifier>
<C00302_ProcedureCode>96372</C00302_ProcedureCode>
<C00307_Description>NO DESCRIPTION</C00307_Description>
</ns0:C003_CompositeMedicalProcedureIdentifier>
<SV102_LineItemChargeAmount>82.56</SV102_LineItemChargeAmount>
<SV103_UnitorBasisforMeasurementCode>UN</SV103_UnitorBasisforMeasurementCode>
<SV104_ServiceUnitCount>2</SV104_ServiceUnitCount>
<ns0:C004_CompositeDiagnosisCodePointer>
<C00401_DiagnosisCodePointer>2</C00401_DiagnosisCodePointer>
</ns0:C004_CompositeDiagnosisCodePointer>
</ns0:SV1_ProfessionalService>
<ns0:DTP_SubLoop_2>
<ns0:DTP_Date_ServiceDate>
<DTP01_DateTimeQualifier>472</DTP01_DateTimeQualifier>
<DTP02_DateTimePeriodFormatQualifier>RD8</DTP02_DateTimePeriodFormatQualifier>
<DTP03_ServiceDate>20160627-20160627</DTP03_ServiceDate>
</ns0:DTP_Date_ServiceDate>
</ns0:DTP_SubLoop_2>
</ns0:TS837_2400_Loop>
</ns0:TS837_2300_Loop>
</ns0:TS837_2000B_Loop>
</ns0:TS837_2000A_Loop>
</ns0:X12_00501_837_P>
</TransactionSet>
</ns1:X12EnrichedMessage>'
IF OBJECT_ID(N'tempdb..#CLAIM_XML', N'U') IS NOT NULL
DROP TABLE #CLAIM_XML;
CREATE TABLE #CLAIM_XML (
CLAIM_SOURCE_ID VARCHAR(20) NOT NULL
,RAW_XML XML NOT NULL
,CLAIM_FORM_TYPE CHAR(1) NOT NULL
,CREATED_DATE DATE NOT NULL
,CONSTRAINT CLAIM_XML_PK PRIMARY KEY (CLAIM_SOURCE_ID)
);
CREATE PRIMARY XML INDEX CLAIM_XML_RAW_XML_IDX
ON #CLAIM_XML (RAW_XML);
INSERT INTO #CLAIM_XML
([CLAIM_SOURCE_ID]
,[RAW_XML]
,[CLAIM_FORM_TYPE]
,[CREATED_DATE])
VALUES('16202E123456'
,#XML
,'H'
,CONVERT(DATE, DATEADD(DAY, -1, GETDATE())));
WITH XMLNAMESPACES ('http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/EnrichedMessageXML' AS ns1
,'http://schemas.microsoft.com/BizTalk/EDI/X12/2006' AS ns0)
SELECT [CX].[CLAIM_SOURCE_ID]
,[ITEM_NUMBER] = LineNumber.ref.value('text()[1]', 'int')
,[HCPCS_LINE_CODE] = [CX].[RAW_XML].value('(/ns1:X12EnrichedMessage/TransactionSet/ns0:X12_00501_837_P/ns0:TS837_2000A_Loop/ns0:TS837_2000B_Loop/ns0:TS837_2300_Loop/ns0:TS837_2400_Loop/ns0:SV1_ProfessionalService/ns0:C003_CompositeMedicalProcedureIdentifier/C00302_ProcedureCode)[1]','varchar(100)')
FROM #CLAIM_XML AS [CX]
CROSS APPLY [CX].[RAW_XML].nodes('/ns1:X12EnrichedMessage/TransactionSet/ns0:X12_00501_837_P/ns0:TS837_2000A_Loop/ns0:TS837_2000B_Loop/ns0:TS837_2300_Loop/ns0:TS837_2400_Loop/ns0:LX_ServiceLineNumber/*') LineNumber(ref)
WHERE [CX].[CLAIM_FORM_TYPE] = 'H'
AND [CX].[CREATED_DATE] = CONVERT(DATE, DATEADD(DAY, -1, GETDATE()));
Use multiple CROSS APPLYs to access the different parts of the XML, like this:
;WITH XMLNAMESPACES ('http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/EnrichedMessageXML' AS ns1
,'http://schemas.microsoft.com/BizTalk/EDI/X12/2006' AS ns0)
SELECT
c.[CLAIM_SOURCE_ID],
sln.c.value('(LX01_AssignedNumber/text())[1]', 'INT') AS [ITEM_NUMBER],
ps.c.value('(ns0:C003_CompositeMedicalProcedureIdentifier/C00302_ProcedureCode/text())[1]', 'INT') AS [HCPCS_LINE_CODE]
FROM #CLAIM_XML c
CROSS APPLY c.[RAW_XML].nodes('/ns1:X12EnrichedMessage/TransactionSet/ns0:X12_00501_837_P/ns0:TS837_2000A_Loop/ns0:TS837_2000B_Loop/ns0:TS837_2300_Loop/ns0:TS837_2400_Loop') l(c)
CROSS APPLY l.c.nodes('ns0:LX_ServiceLineNumber') sln(c)
CROSS APPLY l.c.nodes('ns0:SV1_ProfessionalService') ps(c)
No need for multiple CROSS APPLY with .nodes(). As the values you want to read are single occurance within their tree you can address them directly:
;WITH XMLNAMESPACES ('http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/EnrichedMessageXML' AS ns1
,'http://schemas.microsoft.com/BizTalk/EDI/X12/2006' AS ns0)
SELECT
loop2400.value('(ns0:LX_ServiceLineNumber/LX01_AssignedNumber)[1]', 'INT') AS [ITEM_NUMBER],
loop2400.value('(ns0:SV1_ProfessionalService/ns0:C003_CompositeMedicalProcedureIdentifier/C00302_ProcedureCode)[1]', 'INT') AS [HCPCS_LINE_CODE]
FROM #xml.nodes('/ns1:X12EnrichedMessage/TransactionSet/ns0:X12_00501_837_P/ns0:TS837_2000A_Loop/ns0:TS837_2000B_Loop/ns0:TS837_2300_Loop/ns0:TS837_2400_Loop') A(loop2400)
The lazy approach works too, but - in general - it's good advise to be as specific as possible...
SELECT
loop2400.value('(*//LX01_AssignedNumber)[1]', 'INT') AS [ITEM_NUMBER],
loop2400.value('(*//C00302_ProcedureCode)[1]', 'INT') AS [HCPCS_LINE_CODE]
FROM #xml.nodes('//*:TS837_2400_Loop') A(loop2400)

CROSS APPLY to namespace, sub nodes returns duplicate records

I have this xml (removed most of it for readability). I get wrong records. Wrong chemical names fetched for every CAS_Number. One CAS_Number means one chemical. But here, for the same CAS_number, I have different chemical names.
It's the problem in my cross apply but I couldn't figure it out.
<ArrayOfCatalogItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CatalogItem Version="1">
<Msds xmlns="http://3ecompany.com/webservices/catalogitemxml">
<ProductIdentifiers xmlns="http://3ecompany.com/webservices/catalogitemxml">
<Identifier>M007628</Identifier>
<Source>CPN</Source>
<FirstExportDate xsi:nil="true" />
<LastExportDate xsi:nil="true" />
<FlaggedForResend xsi:nil="true" />
</ProductIdentifiers>
<Ingredients>
<ChemicalName>Hexane</ChemicalName>
<Cas>000110-54-3</Cas>
<AvgPercent>20.000000</AvgPercent>
</Ingredients>
<Ingredients>
<ChemicalName>2-Propanone</ChemicalName>
<Cas>000067-64-1</Cas>
<AvgPercent>20.000000</AvgPercent>
</Ingredients>
<Ingredients>
<ChemicalName>Petroleum gases, liquefied, sweetened</ChemicalName>
<Cas>068476-86-8</Cas>
</Ingredients>
</Msds>
</CatalogItem>
</ArrayOfCatalogItem>
The stored procedure goes like this:
DECLARE #XmlTable TABLE (XMLDATA XML)
INSERT INTO #XmlTable(XMLData)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn
FROM OPENROWSET(BULK 'C:\AA.Sample.File.LUS.Pilly-oneCI.xml', SINGLE_BLOB) AS x;
;WITH XMLNAMESPACES ('http://3ecompany.com/webservices/catalogitemxml' as CI)
SELECT
--CIVersion = CI.value('#Version', 'int'),
Identifier = PID.value('(.)\[1\]', 'varchar(9)'),
Product_Name = MSDSPN.value('(.)\[1\]','varchar(100)'),
CAS_Number = CAS.value('(.)\[1\]', 'varchar(20)'),
Chemical_Name = CN.value('(.)\[1\]', 'varchar(100)')
FROM
#XmlTable
CROSS APPLY
XMLData.nodes('/ArrayOfCatalogItem/CatalogItem') AS XT(CI)
OUTER APPLY
CI.nodes('CI:ProductIdentifiers/CI:Identifier') AS XT2(PID)
CROSS APPLY
CI.nodes('CI:Msds/CI:Ingredients/CI:Cas') AS XT18(CAS)
CROSS APPLY
CI.nodes('CI:Msds/CI:Ingredients/CI:ChemicalName') AS XT19(CN)
Try this:
;WITH XMLNAMESPACES ('http://3ecompany.com/webservices/catalogitemxml' as CI)
SELECT
Identifier = CI.value('(CI:ProductIdentifiers[1]/CI:Identifier)[1]', 'varchar(9)'),
CAS_Number = Ingred.value('(CI:Cas)[1]', 'varchar(20)'),
Chemical_Name = Ingred.value('(CI:ChemicalName)[1]', 'varchar(100)')
FROM
#XmlTable
CROSS APPLY
XMLData.nodes('/ArrayOfCatalogItem/CatalogItem/CI:Msds') AS XT(CI)
CROSS APPLY
CI.nodes('CI:Ingredients') AS XT18(Ingred)
I get a list of XML fragments for each <Msds> node, and from this I grab the ProductIdentifiers info. Plus, from this node, I also get a list of sub-XML-fragments for the <Ingredients> nodes, and grab detailed into from these.
My output looks like this:

How to extract results from SOAP response using XQuery in SQL Server?

I have a SOAP response with below structure and need to get the all the values for the below tags 1. result , documentNumber , costElementCode .
This is my XML sample :
DECLARE #myXML XML = '<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/">123456789</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>
<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>'
I have tried using the below but only get the first value and not all nodes :
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
You can use OUTER APPLY to shred XML data type into multiple rows. This is one example for extracting multiple costElementCodes value (implementing for the other elements should be trivial) :
SELECT x.value('.[1]', 'VARCHAR(256)') as costElementCode
FROM #myXML.nodes('/commitmentsResponse/value/commitmentLine') t(c)
OUTER APPLY t.c.nodes('costElementCode') cec(x)

TSQL and Soap Envelope

with the following query Im trying to Read MessageID and DocPurpose. but only Message ID is showing fine.... Can anyone tellme what Im missing? It will be apreciated
Declare #XmlData XML =
'<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>e96d3ee4-5cca-4b3e-be60-d1284a0fb02f</MessageId>
<Company>CompanyX</Company>
<Action>http://schemas.microsoft.com/dynamics/2008/01/services/ReturnOrderInService/create</Action>
<ConversationId>320034ab-f5ee-41b0-ba35-e0669c2bf1b8</ConversationId>
<RequestMessageId>e96d3ee4-5cca-4b3e-be60-d1284a0fb02f</RequestMessageId>
</Header>
<Body>
<MessageParts>
<ReturnOrderIn xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/ReturnOrderIn">
<DocPurpose xmlns="">Original</DocPurpose>
<SenderId xmlns="">Xcorp</SenderId>
<SalesTable class="entity" xmlns="">
<_DocumentHash>63cf8580-92fe-4b17-b15c-8e619eecf71f</_DocumentHash>
<CurrencyCode>USD</CurrencyCode>
<CustAccount>147854</CustAccount>
<LanguageId>en-us</LanguageId>
<Reservation>None</Reservation>
<ReturnDeadline>2014-10-10</ReturnDeadline>
<ReturnReasonCodeId>Reason</ReturnReasonCodeId>
<SalesName>Stores</SalesName>
<SalesLine class="entity">
<DefaultDimension>
<Values xmlns="http://schemas.microsoft.com/dynamics/2008/01/sharedtypes">
<Value>
<Name>Site</Name>
<Value>VN</Value>
</Value>
</Values>
</DefaultDimension>
<ExpectedRetQty>-5</ExpectedRetQty>
<ItemId>Else</ItemId>
<Name>Something</Name>
<PriceUnit>11.00</PriceUnit>
<SalesQty>-15.00</SalesQty>
</SalesLine>
</SalesTable>
</ReturnOrderIn>
</MessageParts>
</Body>
</Envelope>'
Declare #MessageId varchar(50)
;WITH XMLNAMESPACES('http://schemas.microsoft.com/dynamics/2011/01/documents/Message' As a,
'http://schemas.microsoft.com/dynamics/2008/01/documents/ReturnOrderIn' As b,
default 'http://schemas.microsoft.com/dynamics/2011/01/documents/Message')
Select #MessageId =MessageId from
(SELECT
t.c.value('a:MessageId[1]', 'varchar(50)') MessageId
FROM #XmlData.nodes('/Envelope/Header') AS t(c)) x
Declare #DocPurpose varchar(50)
;WITH XMLNAMESPACES('http://schemas.microsoft.com/dynamics/2011/01/documents/Message' As a,
'http://schemas.microsoft.com/dynamics/2008/01/documents/ReturnOrderIn' As b,
default 'http://schemas.microsoft.com/dynamics/2011/01/documents/Message')
Select #DocPurpose = DocPurpose from
(SELECT
t.d.value('b:DocPurpose[1]', 'varchar(50)') DocPurpose
FROM #XmlData.nodes('Envelope/body/MessageParts/b:ReturnOrderIn') AS t(d))z
Print 'MessageID>>>>>>' + #MessageId
Print #DocPurpose
<DocPurpose xmlns=""> node is in empty namespace, not the default namespace. Since we can't declare a prefix to map empty namespace URI, just don't declare a default in ;WITH XMLNAMESPACES block. Try this way :
Declare #DocPurpose varchar(50)
;WITH XMLNAMESPACES
('http://schemas.microsoft.com/dynamics/2011/01/documents/Message' As a,
'http://schemas.microsoft.com/dynamics/2008/01/documents/ReturnOrderIn' As b)
Select #DocPurpose = DocPurpose from
(
SELECT t.d.value('DocPurpose[1]', 'varchar(50)') DocPurpose
FROM #XmlData.nodes('a:Envelope/a:Body/a:MessageParts/b:ReturnOrderIn') AS t(d)
)z
Small thing but matter, you need uppercase B for Body.

Resources