Parsing XML in T-SQL - ABS data - sql-server

I'm after some assistance parsing an xml file provided by the Australian Bureau of Statistics. I've read over everything I can find here and online, and am not having much luck reading this data.
This is a sample of the XML:
<?xml version='1.0' encoding='UTF-8'?>
<message:MessageGroup xmlns:message="http://www.w3.org/2001/XMLSchema" xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic" xmlns:common="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic http://www.sdmx.org/docs/2_0/SDMXGenericData.xsd http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message http://www.sdmx.org/docs/2_0/SDMXMessage.xsd">
<Header xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message">
<ID>none</ID>
<Test>false</Test>
<Truncated>false</Truncated>
<Prepared>2018-02-14T22:41:03</Prepared>
<Sender id="ABS">
<Name xml:lang="en">Australian Bureau of Statistics</Name>
<Name xml:lang="fr">Australian Bureau of Statistics</Name>
</Sender>
</Header>
<DataSet keyFamilyURI="http://stat.data.abs.gov.au/restsdmx/sdmx.ashx/GetKeyFamily/RES_PROP_INDEX">
<KeyFamilyRef>RES_PROP_INDEX</KeyFamilyRef>
<Series>
<SeriesKey>
<Value concept="MEASURE" value="1" />
<Value concept="PROP_TYPE" value="3" />
<Value concept="ASGS_2011" value="3GBRI" />
<Value concept="FREQUENCY" value="Q" />
</SeriesKey>
<Attributes>
<Value concept="TIME_FORMAT" value="P3M" />
</Attributes>
<Obs>
<Time>2015-Q1</Time>
<ObsValue value="112.7" />
</Obs>
<Obs>
<Time>2015-Q2</Time>
<ObsValue value="113.7" />
</Obs>
</Series>
<Series>
<SeriesKey>
<Value concept="MEASURE" value="1" />
<Value concept="PROP_TYPE" value="3" />
<Value concept="ASGS_2011" value="5GPER" />
<Value concept="FREQUENCY" value="Q" />
</SeriesKey>
<Attributes>
<Value concept="TIME_FORMAT" value="P3M" />
</Attributes>
<Obs>
<Time>2015-Q1</Time>
<ObsValue value="114.4" />
</Obs>
<Obs>
<Time>2015-Q2</Time>
<ObsValue value="113.4" />
</Obs>
</Series>
<Annotations>
<common:Annotation>
<common:AnnotationTitle>Statistical usage warning</common:AnnotationTitle>
<common:AnnotationText>ABS.Stat beta is continuing to be developed. Data will be updated as soon as possible following its 11:30 am release on the ABS website.</common:AnnotationText>
</common:Annotation>
</Annotations>
</DataSet>
</message:MessageGroup>
The result set should return 3 values:
SeriesKey Value where Concept = 'ASGS_2011'
Obs "Time" Value
Obs "Obsvalue" Value
e.g the first record would return a row like:
3GBRI | 2015-Q1 | 112.7
This sample would return 4 rows of data like this.
I've tried inserting the XML into an XML variable or a column in a DB with an XML datatype, and then using SQL's XML functionality, but I'm an absolute novice at this and am having trouble with the correct coding/approach.
Any advice or sample code would be greatly appreciated.

I'd suggest do get rid of the <?xml blah ?> declaration. This is only useful when you store an XML to a file. Within SQL-Server any XML's encoding is fixed to unicode / UCS-2. This can lead to encoding problems...
There are namespaces involved...
DECLARE #xml XML=
'<?xml version=''1.0'' encoding=''UTF-8''?>
<message:MessageGroup xmlns:message="http://www.w3.org/2001/XMLSchema" xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic" xmlns:common="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/common" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic http://www.sdmx.org/docs/2_0/SDMXGenericData.xsd http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message http://www.sdmx.org/docs/2_0/SDMXMessage.xsd">
<Header xmlns="http://www.SDMX.org/resources/SDMXML/schemas/v2_0/message">
<ID>none</ID>
<Test>false</Test>
<Truncated>false</Truncated>
<Prepared>2018-02-14T22:41:03</Prepared>
<Sender id="ABS">
<Name xml:lang="en">Australian Bureau of Statistics</Name>
<Name xml:lang="fr">Australian Bureau of Statistics</Name>
</Sender>
</Header>
<DataSet keyFamilyURI="http://stat.data.abs.gov.au/restsdmx/sdmx.ashx/GetKeyFamily/RES_PROP_INDEX">
<KeyFamilyRef>RES_PROP_INDEX</KeyFamilyRef>
<Series>
<SeriesKey>
<Value concept="MEASURE" value="1" />
<Value concept="PROP_TYPE" value="3" />
<Value concept="ASGS_2011" value="3GBRI" />
<Value concept="FREQUENCY" value="Q" />
</SeriesKey>
<Attributes>
<Value concept="TIME_FORMAT" value="P3M" />
</Attributes>
<Obs>
<Time>2015-Q1</Time>
<ObsValue value="112.7" />
</Obs>
<Obs>
<Time>2015-Q2</Time>
<ObsValue value="113.7" />
</Obs>
</Series>
<Series>
<SeriesKey>
<Value concept="MEASURE" value="1" />
<Value concept="PROP_TYPE" value="3" />
<Value concept="ASGS_2011" value="5GPER" />
<Value concept="FREQUENCY" value="Q" />
</SeriesKey>
<Attributes>
<Value concept="TIME_FORMAT" value="P3M" />
</Attributes>
<Obs>
<Time>2015-Q1</Time>
<ObsValue value="114.4" />
</Obs>
<Obs>
<Time>2015-Q2</Time>
<ObsValue value="113.4" />
</Obs>
</Series>
<Annotations>
<common:Annotation>
<common:AnnotationTitle>Statistical usage warning</common:AnnotationTitle>
<common:AnnotationText>ABS.Stat beta is continuing to be developed. Data will be updated as soon as possible following its 11:30 am release on the ABS website.</common:AnnotationText>
</common:Annotation>
</Annotations>
</DataSet>
</message:MessageGroup>';
--The query will declare the needed namespaces and then use .nodes() to get the <Series> and a second call to .nodes() to get the nested <Obs>:
WITH XMLNAMESPACES(DEFAULT 'http://www.SDMX.org/resources/SDMXML/schemas/v2_0/generic'
,'http://www.w3.org/2001/XMLSchema' AS message)
SELECT ser.value(N'(SeriesKey/Value[#concept="ASGS_2011"]/#value)[1]',N'nvarchar(max)') AS Concept
,obs.value(N'(Time/text())[1]',N'nvarchar(max)') AS [Time]
,obs.value(N'(ObsValue/#value)[1]',N'decimal(10,4)') AS ObsValue
FROM #xml.nodes(N'/message:MessageGroup/DataSet/Series') AS A(ser)
OUTER APPLY A.ser.nodes(N'Obs') AS B(obs);
The result
Concept Time ObsValue
3GBRI 2015-Q1 112.7000
3GBRI 2015-Q2 113.7000
5GPER 2015-Q1 114.4000
5GPER 2015-Q2 113.4000

Related

FetchXML for SQL Join having filter

I am trying to build FetchXML equivalent of SQL query, I am quite new in using FetchXML:
SELECT o.opportunityid,c1.accountid
FROM dbo.opportunity o
LEFT JOIN dbo.account c1 on o.customerid = c1.accountid and o.customeridtype = 1
into
<fetch mapping="logical" version="1.0">
<entity name="opportunity">
<attribute name="opportunityid" />
<link-entity name="account" from="accountid" to="customerid" alias="A1" link-type="outer" >
<filter type="and" >
<condition attribute="customeridtype" operator="eq" value="1" />
</filter>
<attribute name="accountid" />
</link-entity>
but this is throwing error saying that attribute "customeridtype" doesn't exist in entity "account". that attribute is from opportunity entity as in SQL query. How can I fix this?
I just fired this in one of my Dynamics instance and gave correct result
<fetch>
<entity name="opportunity" >
<attribute name="opportunityid" />
<attribute name="customeridtype" />
<filter type="and" >
<condition attribute="customeridtype" operator="eq" value="1" />
</filter>
<link-entity name="account" from="accountid" to="customerid" link-type="outer" alias="Account" >
<attribute name="accountid" alias="AccountId" />
</link-entity>
</entity>
</fetch>
Take out the filter from inside link-entity xml node to outside entity node.
You can try XrmToolBox fetchxml builder or Kingswaysoft sql2fetchxml online tool.
<fetch mapping="logical" version="1.0">
<entity name="opportunity">
<attribute name="opportunityid" />
<filter type="and" >
<condition attribute="customeridtype" operator="eq" value="1" />
</filter>
<link-entity name="account" from="accountid" to="customerid" alias="A1" link-type="outer" >
<attribute name="accountid" />
</link-entity>

SQL Server stored procedure - Table to XML object

I need to write a stored procedure that can create the following output from values from a SQL Server table:
<object>
<ValueList>
<Value value="1" text="Name" enabled="1" alias="Alias" />
<Value value="2" text="Name" enabled="1" alias="Alias" />
<Value value="3" ....
...
...
</ValueList>
</object>
I have tried to convert my table into XML using this procedure:
select TXT as [text]
from lit_geography
for XML raw ('value'), root('object')
Then I get the following
<object>
<value text="Midler tidig havn" />
<value text="Færgehavnsvej" />
<value text="Sydhavnsvej" />
<value text="Ø-Pladsen" />
<value text="Havnepladsen" />
</object>
TODO:
I am missing the parent node Valuelist
I need to append the following:
value="1", value="2" etc etc counting up for each value
enabled="1"
alias=""
For the incremental value, you can use Row_Number()
Example
Select (
Select [value] = row_number() over (Order by (select null))
,[text] = txt
,[enabled] = 1
,[alias] = 'Alias'
From lit_geography
For XML Raw('Value'),type
)
For XML Path('ValueList'),Root('object')
Returns
<object>
<ValueList>
<Value value="1" text="Midler tidig havn" enabled="1" alias="Alias" />
<Value value="2" text="Færgehavnsvej" enabled="1" alias="Alias" />
<Value value="3" text="Sydhavnsvej" enabled="1" alias="Alias" />
<Value value="4" text="Ø-Pladsen" enabled="1" alias="Alias" />
<Value value="5" text="Havnepladsen" enabled="1" alias="Alias" />
</ValueList>
</object>
EDIT - Requested UPDATE
Update lit_formfield set [Values] = (
Select (
Select [value] = row_number() over (Order by (select null))
,[text] = txt
,[enabled] = 1
,[alias] = 'Alias'
From lit_geography
For XML Raw('Value'),type
)
For XML Path('ValueList'),Root('object')
)
Where Label = 'listbox'

Guide or any tool to convert FetchXML to SQL Query

I have below FetchXML query used to create report in Business Intelligent Development Studio.
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="incident">
<attribute name="ticketnumber" />
<attribute name="createdon" />
<attribute name="statuscode" />
<attribute name="incidentid" />
<attribute name="caseorigincode" />
<attribute name="new_statussla" />
<attribute name="ownerid" />
<attribute name="new_caseaging" />
<attribute name="casetypecode" />
<order attribute="ticketnumber" descending="false" />
<filter type="and">
<condition attribute="createdon" operator="on-or-after" value="#Startdate" />
<condition attribute="createdon" operator="on-or-before" value="#Enddate" />
<condition attribute="caseorigincode" operator="ne" value="3" />
</filter>
<link-entity name="systemuser" from="systemuserid" to="owninguser" visible="false" link-type="outer" alias="a_cf39b8fda77b421483a1af5e511c39ca">
<attribute name="new_region" />
<attribute name="businessunitid" />
</link-entity>
</entity>
</fetch>
I do converting this query to SQL query like below.
SELECT a.ticketnumber, a.createdon, a.statuscode,
a.incidentid, a.caseorigincode, a.new_statussla,
a.ownerid, a.new_caseaging, a.casetypecode,
b.new_region, b.businessunitid
FROM FilteredIncident a, FilteredSystemUser b
WHERE a.ownerid = b.systemuserid
AND createdon >= #StartDate
AND creaedon <= #EndDate
AND caseorigincode != '3'
My Question, is my SQL Query correct ? Eventhough I can execute it.
Well out of need I just created this. FetchXML to SQL Convertor free on GitHub!
A work in progress, but will give a usable output. Do Try! https://github.com/abtevrythng/FetchXML-to-SQL
here is the generated output for your fetchXML:
SELECT incident.ticketnumber, incident.createdon, incident.statuscode, incident.incidentid, incident.caseorigincode, incident.new_statussla, incident.ownerid, incident.new_caseaging, incident.casetypecode, systemuser.new_region, systemuser.businessunitid
FROM incident
LEFT OUTER JOIN systemuser ON incident.systemuserid = systemuser.owninguser
WHERE incident.createdon TBD '#Startdate' AND incident.createdon TBD '#Enddate' AND incident.caseorigincode != '3'

xml.value() method in SQL Server (Getting a value inside an XML query)

I have an XML Query like this:
<ChangeSet xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Change DateTime="2011-12-02T09:01:58.3615661-08:00" UserId="3123">
<Table ChangeType="Insert" Name="EVNT_LN_AFF">
<Keys>
<Key FieldName="DIR_CD" Value="NB" />
<Key FieldName="LN_ID" Value="A" />
<Key FieldName="EVNT_ID" Value="10T000289" />
</Keys>
<ChangedFields>
<Field FieldName="DIR_CD" Previous="" Current="NB" />
<Field FieldName="LN_ID" Previous="" Current="A" />
<Field FieldName="EVNT_ID" Previous="" Current="10T000289" />
<Field FieldName="UD_DTTM" Previous="" Current="12/2/2011 9:01:59 AM" />
<Field FieldName="UD_USER_ID" Previous="" Current="3123" />
</ChangedFields>
</Table>
(The query goes on)
Now I want to use a statement like this:
SELECT TOP 1000 [CHG_LOG_ID]
, [EVNT_ID]
, [DATA_XML_TXT]
, [UD_DTTM]
FROM [MY_PROJ].[dbo].[EVNT_CHG_LOG]
WHERE DATA_XML_TXT.value('(/ChangeSet/Change/Table/ChangedFields/UD_USER_ID)[0]','varchar(50)') like '%3123%'
But when I execute the query, I don't get any results.
I tested the following XQuery, and it should give you what you need:
SELECT TOP 1000 [CHG_LOG_ID]
, [EVNT_ID]
, [DATA_XML_TXT]
, [UD_DTTM]
FROM [MY_PROJ].[dbo].[EVNT_CHG_LOG]
WHERE DATA_XML_TXT.value('(/ChangeSet/Change/Table/ChangedFields/Field[#FieldName="UD_USER_ID"]/#Current)[1]','varchar(50)') like '%3123%'
Note: Indexing for XQuery starts at 1 instead of 0

I'm trying to implement factorial in an xml language

I'm trying to implement factorial in the xml language of xcerion.
<step id="fac">
<alias name="p" value="={$n}*{$p}" />
<alias name="n" value="={$n}-1" />
<operation name="decision">
<when test="'{$n}'>'0'" step="fac" />
</operation>
</step>
<alias name="p" value="1" />
<alias name="n" value="4" />
<operation name="call" value="fac" />
My code works, but I think it's a bit wordy.
How does this language compare with other xml languages?
Especially handling of variables, selection, loops and subroutine calling.

Resources