Get elements of same name from XML using XQuery in SQL server - sql-server

I am having following XML
DECLARE #ruleXML XML
SET #RuleXML = '<questionnaire xmlns:xsi="http://schema1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schem2" title="Sample">
<sections>
<section id="24" title="Section Title" help="" url="">
<questions />
</section>
<section id="23" title="Information" help="" url="">
<questions />
</section>
<section id="25" title="Section Title1" help="" url="">
<questions>
<question id="3" title="Question Text">
<display-rules />
<questions />
</question>
<question id="4" title="Question Text" >
<response-set type="inline" />
<display-rules />
<questions />
</question>
</questions>
</section>
</sections>
</questionnaire>'
How to get a table with question id and title from all the question nodes regardless of their level using XQUERY in SQL server?

; with xmlnamespaces (default 'http://schem2')
select tbl.col1.value('#id', 'int')
, tbl.col1.value('#title', 'varchar(100)')
from #RuleXML.nodes('//question') tbl(col1)
Working example at SQL FIddle.

Related

How to loop xml in store procedure

I have a store procedure that returns the below XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header />
<SOAP-ENV:Body>
<ns2:ReportResponse>
<ns2:responseTitle />
<ns2:responseBody>
<ns2:resultRow>
<ns2:result Name="country" Value="United Kingdom" />
<ns2:result Name="code" Value="7360" />
</ns2:resultRow>
<ns2:resultRow>
<ns2:result Name="country" Value="France" />
<ns2:result Name="code" Value="7340" />
</ns2:resultRow>
</ns2:responseBody>
</ns2:ReportResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I want to be able to save the 2 records in the table, how can I get a loop to get the data?
Record 1:
Country=United Kingdom
Code=7360
Record 2:
Country=France
Code=7340
I tried to use this select but it's not returning anything.
SELECT
Record.value('#Name','VARCHAR')
FROM #XmlResponse.nodes('/Envelope/Body/ReportResponse/responseBody/resultRow')AS TEMPTABLE(Record)
Thanks.
Like this:
declare #doc xml = '
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header />
<SOAP-ENV:Body>
<ns2:ReportResponse xmlns:ns2="http://whatever">
<ns2:responseTitle />
<ns2:responseBody>
<ns2:resultRow>
<ns2:result Name="country" Value="United Kingdom" />
<ns2:result Name="code" Value="7360" />
</ns2:resultRow>
<ns2:resultRow>
<ns2:result Name="country" Value="France" />
<ns2:result Name="code" Value="7340" />
</ns2:resultRow>
</ns2:responseBody>
</ns2:ReportResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
';
WITH XMLNAMESPACES ('http://schemas.xmlsoap.org/soap/envelope/' as soap ,
'http://whatever' as ns2)
SELECT
Record.value('(ns2:result[#Name="country"])[1]/#Value','VARCHAR(20)') Country,
Record.value('(ns2:result[#Name="code"])[1]/#Value','int') Code
FROM #doc.nodes('/soap:Envelope/soap:Body/ns2:ReportResponse/ns2:responseBody/ns2:resultRow')AS TEMPTABLE(Record)
outputs
Country Code
-------------------- -----------
United Kingdom 7360
France 7340
(2 rows affected)

XML Values to retrieve in single Column with Any(,) Delimiter (2)

declare #x xml =
'<Detials xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Tests>
<Test Name="Test1" TotalMarks="100">95</Test>
<Test Name="Test2" TotalMarks="200">65</Test>
<Test Name="Test3" TotalMarks="150">95</Test>
<Test Name="Test4" TotalMarks="150"></Test>
</Tests>
<Tests>
<Test Name="Test1" TotalMarks="100">95</Test>
<Test Name="Test2" TotalMarks="200">65</Test>
<Test Name="Test3" TotalMarks="150">95</Test>
<Test Name="Test4" TotalMarks="150"></Test>
</Tests>
</Detials>'
When i queried like this
SELECT STUFF(
#x.query('for $a in (*:Detials/Tests/Test/#Name)
return <a>{concat(",", $a)}</a>')
.value('.', 'NVARCHAR(MAX)'),
1, 1, '') AS ListOfName
I get like this
ListofName
Test1,Test2,Test3,Test4,Test1,Test2,Test3,Test4
But Want to shred the xml based on the <Test> Which can give the result like this below
ListofName
Test1,Test2,Test3,Test4
Test1,Test2,Test3,Test4
Please help me here to shred original XML into separate rows before string concatenation with query() and value()
Thanks in Advance ,Jayendran
Try this solution:
declare #x xml =
'<Detials xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Tests>
<Test Name="Test1" TotalMarks="100">95</Test>
<Test Name="Test2" TotalMarks="200">65</Test>
<Test Name="Test3" TotalMarks="150">95</Test>
<Test Name="Test4" TotalMarks="150"></Test>
</Tests>
<Tests>
<Test Name="Test1" TotalMarks="100">95</Test>
<Test Name="Test2" TotalMarks="200">65</Test>
<Test Name="Test3" TotalMarks="150">95</Test>
<Test Name="Test4" TotalMarks="150"></Test>
</Tests>
</Detials>'
-- Edit 1
SELECT XmlTable.OriginalID, ROW_NUMBER() OVER(ORDER BY x.XmlCol) AS RowNum, y.ListOfName
FROM (SELECT 1 AS OriginalID, #x AS XmlCol) AS XmlTable -- Edit 2
CROSS APPLY XMLTable.XmlCol.nodes('*:Detials/Tests') AS x(XmlCol)
CROSS APPLY(
SELECT STUFF(x.XmlCol.query('for $a in (Test/#Name) return <a>{concat(",", $a)}</a>').value('.', 'NVARCHAR(MAX)'), 1, 1, '')
) AS y(ListOfName)
-- End of Edit 1
Demo

How to parse XML column in SQL Server 2012?

I have never used XML parsing in SQL Server, I would like to extract the fields in its own column, get the correct data.
I have a column called CustomerHeaderUncompressed in a Customer table that looks something like below, how do I extract the fields and the data in SQL Server 2012?
<CustomerHeaderData>
<CustomerHeader>
<shippingmethod Value="00000000-0000-0000-0000-000000000000" Name="" />
<discount Value="" />
<customdiscount Value="0" />
<ponumber Value="9909933793" />
<tax1 Value="-1" />
<tax2 Value="-1" />
<tax3 Value="0" />
<tax3name Value="" />
<tax4 Value="0" />
<Freight />
<ClientExtraField6 Value="5" />
<ClientExtraField7 Value="3" />
<dateneeded Value="01/01/0001 00:00:00" />
<ClientTaxCodeSource>0</ClientTaxCodeSource>
<shippingbranch />
<dropnumber Value="" />
<comment Value="" />
<shippingzone Value="" />
<salespersonID Value="704e78d4-cdbb-4963-bcc2-2c83a1d5f3fd" />
<salesperson Value="Salesrep, XYZ" />
<installation Value="False" />
<salesterms Value="18" />
<HeldItemDeliveryMethod Value="0" />
<customcontrol>
<CustomCustomerHeader CultureInfo="en-US">
<BusinessSegment>TR</BusinessSegment>
<BusinessSegmentID>1</BusinessSegmentID>
<OrderType>2</OrderType>
<MarketSegment>S3</MarketSegment>
<CustomerDeliveryDate>2010-01-21</CustomerDeliveryDate>
<BuildingPermitNumber />
<FinalWallDepth />
<PricingType>2</PricingType>
<HouseBuiltBefore1978>False</HouseBuiltBefore1978>
<AttributePricing>False</AttributePricing>
<UndeterminedAttributes>False</UndeterminedAttributes>
<EventIDStatus>VerifyFailed</EventIDStatus>
<EventIDEnabled>False</EventIDEnabled>
<CustomerDiscount>0</CustomerDiscount>
<PreparedBy />
<RequestedShipDate>01/14/2010</RequestedShipDate>
<UserTestDate>01/01/0001</UserTestDate>
</CustomCustomerHeader>
</customcontrol>
</CustomerHeader>
Basically something like this:
select from your Customer table
use CROSS APPLY and the XQuery .nodes() function to grab the XML as a "on-the-fly" pseudo table of XML fragments (table alias XT, single column aliassed as XC)
"reach" into those XML fragments and pull out the values you need, using the .value() XQuery function; use element names as such, and attributes need to be prefixed with a # sign
Try this and extend it to your needs:
SELECT
ShippingMethodValue = XC.value('(shippingmethod/#Value)[1]', 'varchar(50)'),
ShippingMethodName = XC.value('(shippingmethod/#Name)[1]', 'varchar(50)'),
DiscountValue = XC.value('(discount/#Value)[1]', 'varchar(50)'),
CustomDiscountValue = XC.value('(customdiscount/#Value)[1]', 'varchar(50)'),
PONumber= XC.value('(ponumber/#Value)[1]', 'bigint' )
FROM
Customer
CROSS APPLY
CustomerHeaderUncompressed.nodes('/CustomerHeaderData/CustomerHeader') AS XT(XC)

Sql Server Xml to table logic

I need to query Xml data that has multiple REPORT tag elements. It needs to be filtered to return only the rows where the REPORTID is equal to a given name. I've tried to perform this filter with no luck. Could someone point me in the right direction here using the Sql Server Xml functions?
Basically, I'm looking for my result set to return as a table and look like:
ID
------
1
2
3
Given the following, how would I select out on the rows for the REPORT where the REPORTID (/TEST/REPORT/TITLE[#ReportId = "Report One"]) is equal to 'Report One'?
DECLARE #Xml XML, #ReportId VARCHAR(200);
SET #ReportId = 'Report One';
SET #Xml = '
<TEST>
<REPORT ReportType="Type One">
<TITLE ReportId="Report One">
<TITLE1>Title One</TITLE1>
</TITLE>
<HEADER>
<Run_Date OrigName="Run Date">4/10/2012</Run_Date>
</HEADER>
<BODY>
<TABLE1>
<DATA />
<ROW>
<ID>1</ID>
</ROW>
<ROW>
<ID>2</ID>
</ROW>
<ROW>
<ID>3</ID>
</ROW>
</TABLE1>
</BODY>
</REPORT>
<REPORT ReportType="Type Two">
<TITLE ReportId="Report Two">
<TITLE1>Title Two</TITLE1>
</TITLE>
<HEADER>
<Run_Date OrigName="Run Date">4/10/2012</Run_Date>
</HEADER>
<BODY>
<TABLE1>
<DATA />
<ROW>
<ID>4</ID>
</ROW>
<ROW>
<ID>5</ID>
</ROW>
<ROW>
<ID>6</ID>
</ROW>
</TABLE1>
</BODY>
</REPORT>
</TEST>';
select I.N.value('.', 'int') as ID
from #Xml.nodes('TEST/REPORT') as R(N)
cross apply R.N.nodes('BODY/TABLE1/ROW/ID') as I(N)
where R.N.exist('TITLE[#ReportId = sql:variable("#ReportId")]') = 1
I realize this is almost three years old, but I couldn't resist. The CROSS APPLY is unnecessary if you expand the XPATH expression in nodes().
SELECT ID = c.value('.', 'int')
FROM #Xml.nodes('/TEST/REPORT[TITLE/#ReportId=sql:variable("#ReportId")]/BODY/TABLE1/ROW/ID') x(c)

How to work in Crystal Report with Object Data Source?

How to work in Winforms Crystal Report with Object Data Source?
So far I have found web-links to use Crystal Report with DataSets or Databases directly.
Can anyone show me how to do it like this?
its the same as before...
reportDocument.SetDataSource(List1);
<CR:CrystalReportViewer ID="crvmyDataReport" runat="server"
ReportSourceID="crsmyData" EnableDatabaseLogonPrompt="False" DisplayGroupTree="False"
EnableParameterPrompt="False" ReuseParameterValuesOnRefresh="True"
BorderStyle="Solid" BorderColor="Black" BorderWidth="1px" />
<br />
<CR:CrystalReportSource ID="crsmyData" runat="server">
<Report FileName="myData.rpt">
<DataSources>
<CR:DataSourceRef DataSourceID="odsmyData" TableName="myData" />
</DataSources>
</Report>
</CR:CrystalReportSource>
<asp:ObjectDataSource ID="odsmyData" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="myDataQuery"
TypeName="myDataAppTableAdapters.myDataTableAdapter">
<SelectParameters>
<asp:ControlParameter ControlID="tb1" ConvertEmptyStringToNull="False"
DbType="String" Name="p1" PropertyName="Text" />
<asp:ControlParameter ControlID="tb2" ConvertEmptyStringToNull="False"
DbType="String" Name="p2" PropertyName="Text" />
<asp:ControlParameter ControlID="tb3" ConvertEmptyStringToNull="False"
DbType="String" Name="p3" PropertyName="Text" />
<asp:ControlParameter ControlID="ddl1" ConvertEmptyStringToNull="False"
DbType="String" Name="p4" PropertyName="SelectedValue" />
</SelectParameters>
</asp:ObjectDataSource>

Resources