Creating XML from MSSQL - sql

How can I create the following XML from MS SQL?
I've looked and google and cant see for my specific example as below, thanks.
This would be from an SQL query using XML PATH in some manner.
<message>
<header date="15/07/2016" userid="QUOTEJOB">
<schema name="TKJobLoaderSchema" version="1.0" />
<source system="" product="" productversion="" />
<destination system="" product="" productversion="" />
</header>
<body>
<jobs>
<job action="jmCreate" company="02" contract="QW" description="test job" job_type="02" priority="5" created_by="QUOTEJOB">
<job_lines>
<job_line line_no="1" line_type="SOR" code="AQW" quantity="1916.5" />
</job_lines>
<job_narratives>
<job_narrative id="2" narrative="4678f874-314c-4584-99e3-c69e3af71999" />
</job_narratives>
<job_property company="02" ref="02363" />
</job>
</jobs>
</body>
</message>

Assuming, that every value is 1:1 your given sample can be created like the following (replace the literals with your actual column names, variables, whatever):
SELECT {d'2016-07-15'} AS [header/#date]
,'QUOTEJOB' AS [header/#userid]
,'TKJobLoaderSchema' AS [header/schema/#name]
,'1.0' AS [header/schema/#version]
,'' AS [header/source/#system]
,'' AS [header/source/#product]
,'' AS [header/source/#productversion]
,'' AS [header/destination/#system]
,'' AS [header/destination/#product]
,'' AS [header/destination/#productversion]
,'jmCreate' AS [body/jobs/job/#action]
,'02' AS [body/jobs/job/#company]
--more attributes of <job>
,1 AS [body/jobs/job/job_lines/job_line/#line_no]
--more attributes of <job_line>
,2 AS [body/jobs/job/job_narratives/job_narrative/#id]
--more attributes of <job_narrative>
,'02' AS [body/jobs/job/job_property/#company]
,'02363' AS [body/jobs/job/job_property/#ref]
FOR XML PATH('message')
The result
<message>
<header date="2016-07-15T00:00:00" userid="QUOTEJOB">
<schema name="TKJobLoaderSchema" version="1.0" />
<source system="" product="" productversion="" />
<destination system="" product="" productversion="" />
</header>
<body>
<jobs>
<job action="jmCreate" company="02">
<job_lines>
<job_line line_no="1" />
</job_lines>
<job_narratives>
<job_narrative id="2" />
</job_narratives>
<job_property company="02" ref="02363" />
</job>
</jobs>
</body>
</message>

Related

Select data using WHERE condition on XML data column in SQL table

I have a table that lists some user details.
ID
GUID
Username
Password
Data
1
a2a8s7d4d
xswe
xxxxxx
XML
2
aer335mla
user
xxxxxx
XML
The Data column contains data using XML. Below is a sample from the table.
<UserInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ComponentFramework">
<ActiveDirectoryUser>false</ActiveDirectoryUser>
<CanUpdateMasterData>false</CanUpdateMasterData>
<CanUploadFiles>false</CanUploadFiles>
<ChangePassword>false</ChangePassword>
<CustomDataPageSize>false</CustomDataPageSize>
<CustomMasterDataPageSize>false</CustomMasterDataPageSize>
<DataPageSize>100</DataPageSize>
<Disabled>true</Disabled>
<Displayname>Pål</Displayname>
<Email i:nil="true" />
<EnforcePasswordPolicy>false</EnforcePasswordPolicy>
<EnvironmentIdList xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<GUID i:nil="true" />
<GeoLocation>
<City i:nil="true" />
<Country i:nil="true" />
<CountryCode i:nil="true" />
<Ip i:nil="true" />
<Isp i:nil="true" />
<Lat>0</Lat>
<Lon>0</Lon>
<Org i:nil="true" />
<Query i:nil="true" />
<Region i:nil="true" />
<RegionName i:nil="true" />
<Status i:nil="true" />
<Timezone i:nil="true" />
<Zip i:nil="true" />
</GeoLocation>
<GroupIdList xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<HttpLink i:nil="true" />
<JobIdList xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<LastLoggedIn>2015-06-11T19:04:44.6407074+05:30</LastLoggedIn>
<MasterDataPageSize>1000</MasterDataPageSize>
<ModifyImages>false</ModifyImages>
<QualityControl>false</QualityControl>
<QualityControlGroupId i:nil="true" />
<Review>false</Review>
<ReviewGroupId i:nil="true" />
<SecurityToken i:nil="true" />
<ShowTrackerPage>false</ShowTrackerPage>
<StatIdList xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<Username><new user></Username>
<Usertype>Power</Usertype>
</UserInfo>
I'm trying to match users that have their accounts disabled. Using the below sql query.
select * from [ATC_Config].[dbo].[Users] where [ATC_Config].[dbo].[Users].[Data].value('/UserInfo/Disabled[1]','nvarchar(MAX)') = 'true'
But SSMS is giving me an error Cannot call methods on nvarchar(max) and highlight my column which Data. I tried few suggestions in SO and in MSDN but nothing helped. Can someone show me what am I doing wrong?
Because your sample XML contains a default namespace definition you'll need to declare that in your value XQuery or via with xmlnamespaces.
Here's how you can do that with value...
select *
from dbo.Users
where cast(Data as xml).value(N'
declare default element namespace "http://schemas.datacontract.org/2004/07/ComponentFramework";
(/UserInfo/Disabled)[1]',N'nvarchar(max)') = N'true';
Or by using with xmlnamespaces:
with xmlnamespaces(default N'http://schemas.datacontract.org/2004/07/ComponentFramework')
select *
from dbo.Users
where cast(Data as xml).value(N'(/UserInfo/Disabled)[1]', N'nvarchar(max)') = N'true';
You need to add the namespace, and you need to cast the value to xml. This is easier if you use with because it applies to the whole query.
A slightly more efficient version of #AlwaysLearning's answer is to use exist and /text()
with xmlnamespaces (
default N'http://schemas.datacontract.org/2004/07/ComponentFramework'
)
select *
from dbo.Users u
where cast(u.Data as xml).exist(N'/UserInfo/Disabled[text() = "true"]') = 1;
db<>fiddle
I strongly suggest you store the Data column as xml in the first place, as casting is inefficient.

SQL XML load with OpenRow

I am trying to load a XML document (below is an example of how I receive the files. I can read the xml, but I am unable to insert the the data into tables. Any help would be appreciative.
<xml xmlns:dt="urn:dt" xmlns:msxsl="urn:schemas-microsoft-com:xslt" dateofservice="1/1/2016 10:00" mmsid="201599999999" userid="dxxxxx9-xxx0-xxdb-xxx0-e8xxxxxxbcd" npid="dfxxxxx9-6xx0-xxxx-bxx0-exxxc1xxxxxd" surveyid="xxxxxxx-xxxa-exxx-8xxx-xxxx56xxxxefb" memberid="sqlsrfr">
<response qid="801" debug="7" value="H" element="select" />
<response qid="150" debug="8" value="Surfer" element="input" mapfield="lastname" />
<response qid="109" debug="9" value="Sequel" element="input" mapfield="firstname" />
<response qid="57" debug="11" value="01/01/1901" element="input" mapfield="dob" />
<response qid="56" debug="12" value="M" element="input" type="radio" aid="85" />
<response qid="78" debug="13" value="123 Sequel Lane" element="textarea" mapfield="addr1" />
<response qid="126" debug="39" value="Stuff" element="input" row="9" placeholder="Placeholder Desc" customtype="disabled" />
<response qid="128" debug="40" value="Stuff" element="input" row="9" placeholder="Placeholder Desc" customtype="disabled" />
<response qid="305" debug="41" value="More words" element="input" row="9" placeholder="Placeholder Desc" customtype="normal" />
<response qid="579" debug="330" value="1" element="input" type="radio" />
<response qid="580" debug="331" value="1" element="input" type="radio" />
<response qid="716" value="Words for value" calc="1" screening="1" />
<response qid="779" value="More words for value" calc="1" highriskdrug="1" />
- <surveyevents>
<event name="Event Name 2.0.3.7" time="1451495565657" count="1" />
<event name="s2" time="1451495568305" count="2" last="1451495728416" />
<event name="s3" time="1451495577298" count="1" />
<event name="s18" time="1451495601418" count="1" />
<event name="Event Name 2.0.3.7" time="1451495725279" count="1" />
<event name="Event Name 2.0.4.1" time="1453394485181" count="1" />
</surveyevents>
<recapturedata />
</xml>
Given, that you manage to read the XML into a variable, the full (de-normalized) query is this:
You will have to design three tables for MetaData, ResponseData and EventData and insert your data there.
If you need to create kind of IDs have a look on ROW_NUMBER() OVER()
btw: The declared namespaces are not used... and define the fitting datatypes yourself (I took only varchar(max) or int).
WITH XMLNAMESPACES('urn:dt' AS dt
,'urn:schemas-microsoft-com:xslt' AS msxsl)
,MetaData AS
(
SELECT #xml.value('/xml[1]/#dateofservice','varchar(max)') AS md_DateOfService
,#xml.value('/xml[1]/#mmsid','varchar(max)') AS md_MmsID
,#xml.value('/xml[1]/#userid','varchar(max)') AS md_UserID
,#xml.value('/xml[1]/#npid','varchar(max)') AS md_NpID
,#xml.value('/xml[1]/#surveyid','varchar(max)') AS md_SurveyID
,#xml.value('/xml[1]/#memberid','varchar(max)') AS md_MemberID
,#xml.query('.') AS XMLNode
)
SELECT md.md_DateOfService
,md.md_MmsID
,md.md_UserID
,md.md_NpID
,md.md_SurveyID
,md.md_MemberID
,response.value('#qid','int') AS resp_qID
,response.value('#debug','int') AS resp_Debug
,response.value('#value','varchar(max)') AS resp_Value
,response.value('#element','varchar(max)') AS resp_Element
,response.value('#row','int') AS resp_Row
,response.value('#mapfield','varchar(max)') AS resp_MapField
,response.value('#type','varchar(max)') AS resp_Type
,response.value('#aid','int') AS resp_aID
,response.value('#placeholder','varchar(max)') AS resp_Placeholder
,response.value('#customtype','varchar(max)') AS resp_CustomType
,EventRow.value('#name','varchar(max)') AS evnt_Name
,EventRow.value('#time','varchar(max)') AS evnt_Time
,EventRow.value('#count','int') AS evnt_Count
,EventRow.value('#last','varchar(max)') AS evnt_Last
FROM MetaData AS md
CROSS APPLY md.XMLNode.nodes('/xml/response') AS One(response)
CROSS APPLY md.XMLNode.nodes('/xml/surveyevents/event') AS The(EventRow)

Remove attribute from nested fields in xml column in sql

After trying many answers about how to delete a field from a xml column in SQL, I can't still manage to find a way to delete the same attribute in multiple fields. Currently my xml column looks something like this:
<ArrayOfCodes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Code code="001 ">
<price xmlns="http://..." xsi:nil="true" />
<salePrice xmlns="http://..." xsi:nil="true" />
<quantity xmlns="http:/...">1</>
</Code>
<Code code="002 ">
<price xmlns="http://..." xsi:nil="true" />
<salePrice xmlns="http://..." xsi:nil="true" />
<quantity xmlns="http:/...">1</>
</Code>
<Code code="003 ">
<price xmlns="http://..." xsi:nil="true" />
<salePrice xmlns="http://..." xsi:nil="true" />
<quantity xmlns="http:/...">1</>
</Code>
</ArrayOfCodes>
My task is to remove the xmlns attributes in all of the fields. Can you please help me with that?

How to get value from XML in stored procedure?

Can you all help me for this problem?
I want to get value from following XML in sql stored procedure. I don't get vlaue if 'xsi:type="ActiveDirectoryItem"' is in tag 'anyType', and 'ActiveDirectoryItems' tag is also with URLs. How can i do to get only values?
<?xml version="1.0" encoding="utf-8" ?>
<ActiveDirectoryItems xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<Items>
<anyType xsi:type="ActiveDirectoryItem">
<FirstName />
<MiddleInitial />
<LastName />
<DisplayName>Migrate-group</DisplayName>
<UserPrincipalName />
<PostalAddress />
<ResidentialAddress />
<Title />
<HomePhone />
<OfficePhone />
<Mobile />
<Fax />
<Email>Migrate-group#gmail.com</Email>
<Url />
<AccountName>Migrate-group</AccountName>
<DistinguishedName />
<IsAccountActive>false</IsAccountActive>
<ManagedBy />
<Manager />
<CompareType>0</CompareType>
<Description />
<Department />
<Company />
<Type />
</anyType>
</Items>
<GlobalCatalog />
</ActiveDirectoryItems>
The format i want to get is as the following:
DisplayName Email Account Name
Migrate-group Migrate-group#gmail.com Migrate-group
you can use the value keyword
Example:
DECLARE #MyXml XML = '<Root><SomeData>100</SomeData></Root>'
DECLARE #Something INT
SELECT #Something = #MyXml.value('(//Root/SomeData)[1]', 'INT')

How to remove xml nodes without attribute in Sql Server

What is the correct way to remove all child nodes of the root node with a missing attribute from an xml field in Sql Server 2008?
My Xml looks like this, I want to remove all the child nodes of <root> that don't have the ln attribute specified
<root>
<title />
<title />
<questionphrase ln="nl">
<xhtml />
</questionphrase>
<questionphrase ln="en">
<xhtml />
</questionphrase>
<information ln="nl">
<xhtml />
</information>
<information ln="en">
<xhtml />
</information>
<title />
<title ln="en">
value
</title>
<label ln="en">
value
</label>
<title />
<title />
</root>
After the delete the xml should look like this
<root>
<questionphrase ln="nl">
<xhtml />
</questionphrase>
<questionphrase ln="en">
<xhtml />
</questionphrase>
<information ln="nl">
<xhtml />
</information>
<information ln="en">
<xhtml />
</information>
<title ln="en">
value
</title>
<label ln="en">
value
</label>
</root>
Try this:
DECLARE #xml XML = '....'
SET #xml.modify('delete //root/*[not(#ln)]')
SQL FIDDLE DEMO