How to parse xml array in Oracle - sql

I have a xml with accounts array, if the array has 1 account this code works fine, but if the array has more than one account this code doesn't work. Please help.
select x.acc_num --into res
from xmltable (
xmlnamespaces (
default 'http://www.eubank.kz/Bis.Info.ExternalServices.Bank',
'http://schemas.xmlsoap.org/soap/envelope/' AS "s",
'http://www.w3.org/2001/XMLSchema-instance' as "i",
'http://schemas.microsoft.com/2003/10/Serialization/Arrays' as "a"
),
's:Envelope/s:Body/TryGetCardAccountsResponse/TryGetCardAccountsResult/IbanList'
passing xmltype(
'<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<TryGetCardAccountsResponse
xmlns="http://www.eubank.kz/Bis.Info.ExternalServices.Bank">
<TryGetCardAccountsResult
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<IbanList
xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:string>KZ199480018A00166666</a:string>
<a:string>KZ519480061A02366666</a:string>
</IbanList>
<Status>Ok</Status>
</TryGetCardAccountsResult>
</TryGetCardAccountsResponse>
</s:Body>
</s:Envelope>'
)
columns
acc_num varchar2(255) path 'a:string'
) x;

Try:
select x.acc_num --into res
from xmltable (
xmlnamespaces (
default 'http://www.eubank.kz/Bis.Info.ExternalServices.Bank',
'http://schemas.xmlsoap.org/soap/envelope/' AS "s",
'http://www.w3.org/2001/XMLSchema-instance' as "i",
'http://schemas.microsoft.com/2003/10/Serialization/Arrays' as "a"
),
's:Envelope/s:Body/TryGetCardAccountsResponse/TryGetCardAccountsResult/IbanList/a:string'
passing xmltype(
'<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<TryGetCardAccountsResponse
xmlns="http://www.eubank.kz/Bis.Info.ExternalServices.Bank">
<TryGetCardAccountsResult
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<IbanList
xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:string>KZ199480018A00166666</a:string>
<a:string>KZ519480061A02366666</a:string>
</IbanList>
<Status>Ok</Status>
</TryGetCardAccountsResult>
</TryGetCardAccountsResponse>
</s:Body>
</s:Envelope>'
)
columns
acc_num varchar2(255) path '.'
) x;

Related

How to get XML subnodes as strings along with parent attributes?

I need to parse xml which consist of nodes having attributes and subnodes. The result should be attribute of parent with xml of child node
declare #xml xml
set #xml = '<root>
<group Description="firstgroup">
<nodeA age="10" birthplace="Anchorage"/>
<nodeB mode="A" ability="read"/>
</group>
<group Description="nextgroup">
<nodeA age="10" birthplace="London"/>
<nodeB count="2" birthplace="Paris"/>
</group>
</root>'
select
c.value('#Description', 'varchar(max)') as 'Description'
from #xml.nodes('/root/*') as T(c)
The output is
Description
===========
firstgroup
nextgroup
But I need
Description nodeBXML
=========== ========
firstgroup <nodeB mode="A" ability="read"/>
nextgroup <nodeB count="2" birthplace="Paris"/>
select
c.value('#Description', 'varchar(max)') as 'Description'
, c.query('./nodeB') as Content
from #xml.nodes('/root/*') as T(c)
-- Results to:
Description Content
firstgroup <nodeB mode="A" ability="read" />
nextgroup <nodeB count="2" birthplace="Paris" />
Perhaps something like this:
Example
Select c.value('#Description', 'varchar(max)') as 'Description'
,AsString = convert(varchar(max),c.query('./*[2]') )
,AsXML = c.query('./*[2]')
From #xml.nodes('/root/*') as T(c)
Returns

Returning XML structures with SQL

Using the next SQL code, running with Oracle 10:
SELECT xmlserialize
(
document xmlelement
(
"Response", xmlforest
(
'00' AS "ReturnCode"
), xmlagg
(
xmlelement
(
"Students", xmlelement
(
"Student", xmlforest
(
'Some 1' AS "Name",
'1' AS "Id"
)
), xmlelement
(
"Student", xmlforest
(
'Some 2' AS "Name",
'2' AS "Id"
)
)
)
)
) AS CLOB INDENT
) FROM dual
... I get this XML structure:
<Response>
<ReturnCode>00</ReturnCode>
<Students>
<Student>
<Name>Some 1</Name>
<Id>1</Id>
</Student>
<Student>
<Name>Some 2</Name>
<Id>2</Id>
</Student>
</Students>
</Response>
... but, I want to get this one (removing the 'root' element):
<ReturnCode>00</ReturnCode>
<Students>
<Student>
<Name>Some 1</Name>
<Id>1</Id>
</Student>
<Student>
<Name>Some 2</Name>
<Id>2</Id>
</Student>
</Students>
Several attemps like this didnt work. Is mandatory to have a root element?:
SELECT xmlserialize
(
document xmlforest
(
'00' AS "ReturnCode"
), xmlagg
(
xmlelement
(
"Students", xmlelement
(
"Student", xmlforest
(
'Some 1' AS "Name",
'1' AS "Id"
)
), xmlelement
(
"Student", xmlforest
(
'Some 2' AS "Name",
'2' AS "Id"
)
)
)
) AS CLOB INDENT
) FROM dual
Any help will be appreciated. (This is just a simplification of something more complex I need to do in some project).
The question is why you need this? XML should be "Well Formed"
This means:
- XML documents must have a root element
- XML elements must have a closing tag
- XML tags are case sensitive
- XML elements must be properly nested
- XML attribute values must be quoted
Add extract('/*/*') and change document -> content
SELECT xmlserialize
(
content xmlelement
(
"Response", xmlforest
(
'00' AS "ReturnCode"
), xmlagg
(
xmlelement
(
"Students", xmlelement
(
"Student", xmlforest
(
'Some 1' AS "Name",
'1' AS "Id"
)
), xmlelement
(
"Student", xmlforest
(
'Some 2' AS "Name",
'2' AS "Id"
)
)
)
)
).extract('/*/*') AS CLOB INDENT
) FROM dual
The easiest working way i could think is to use replace. See below:
Select replace(Replace(col,'< >',''),'</ >','')
from
(
SELECT xmlserialize
(
document xmlelement
(
" ", xmlforest --Putting a wide space to differentiate from other tags
(
'00' AS "ReturnCode"
), xmlagg
(
xmlelement
(
"Students", xmlelement
(
"Student", xmlforest
(
'Some 1' AS "Name",
'1' AS "Id"
)
), xmlelement
(
"Student", xmlforest
(
'Some 2' AS "Name",
'2' AS "Id"
)
)
)
)
)
) AS COL
FROM dual )
Output:
<ReturnCode>00</ReturnCode>
<Students>
<Student>
<Name>Some 1</Name>
<Id>1</Id>
</Student>
<Student>
<Name>Some 2</Name>
<Id>2</Id>
</Student>
</Students>
DEMO
Removing the root element means you will no longer have a valid XML structure, but rather a sequence of XML structures. You could construct this by using xmlserialize(content ...) instead of xmlserialize(document ....).
SELECT xmlserialize(content xmlforest(
'00' as "ReturnCode",
xmlforest(
xmlforest('Some 1' AS "Name",
'1' AS "Id"
) AS "Student",
xmlforest('Some 2' AS "Name",
'2' AS "Id"
) AS "Student"
) AS "Students"
) AS CLOB INDENT)
FROM DUAL;
You could also use xmlconcat and xmlelement instead of xmlforest, if you prefer:
SELECT xmlserialize(content xmlconcat(
xmlelement("ReturnCode", '00'),
xmlelement("Students",
xmlelement("Student",
xmlelement("Name", 'Some 1'),
xmlelement("Id", '1')
),
xmlelement("Student",
xmlelement("Name", 'Some 2'),
xmlelement("Id", '2')
)
)
) AS CLOB INDENT)
FROM DUAL;

How to convert a string in format "property:value,property2:value" to xml in SQL Server 2008

I need to convert the following text to XML
{"name":"daniel & sophia","age":20,"year":2009,"weight":15.1,"points":3,"alias":"dani,da"}{"name":"charls & lina","age":22,"year":2007,"weight":19.0"points":3,"alias":"carlos,lini"}
to
<participants>
<participant>
<name>daniel & sophia</name>
<age>20</age>
<year>2009</year>
<weight>15.1</weight>
<points>3</points>
<alias>dani,da</alias>
</participant>
<participant>
<name>charls & lina</name>
<age>22</age>
<year>2007</year>
<weight>19.0</weight>
<points>3</points>
<alias>carlos,lini</alias>
</participant>
<participants>
I tried to insert the data to a temporary table and then replace "{}" characteres. Then I tried to convert with XML function but I really don't know how to replicate the name of each item.
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #tmp
CREATE TABLE #tmp
(
Id INT IDENTITY,
Campo VARCHAR(MAX)
)
INSERT INTO #tmp
(
Campo
)
VALUES
(
'{"name":"daniel & sophia","age":20,"year":2009,"weight":15.1,"points":3,"alias":"dani,da"}{"name":"charls & lina","age":22,"year":2007,"weight":19.0"points":3,"alias":"carlos,lini"}'
)
SELECT
CONVERT
(
XML, '<participants>' +
REPLACE
(
REPLACE
(
REPLACE
(
REPLACE(REPLACE((SELECT Campo AS [*] FOR XML PATH('')), '{', '<participant>'),'}','</participant>') + '</participants>'
,'<participant>"'
,'<participant><dato>'
)
, '","'
, '</dato><dato>'
)
, '</participant>'
, '</dato></participant>'
)
)
AS xmlname
FROM #tmp
And this is what I get, but It is wrong:
<participants>
<participant>
<dato>name":"daniel & sophia</dato>
<dato>age":20,"year":2009,"weigth":15.1,"points":3,"alias":"dani,da"</dato>
</participant>
<participant>
<dato>name":"charls & lina</dato>
<dato>age":22,"year":2007,"weigth":19.0,"points":3,"alias":"carlos,lini"</dato>
</participant>
</participants>
NOTE: The amount of The number of nodes within the Participant node is
unknown, it can be more than 100 and I would really like it to be a
dynamic query. (Without using EXEC "sql code")
John Cappelletti's answer is great, as long, as you know the column names in advance. The following approach will help you in cases, where you have to deal with such structures dynamically.
It is ugly, to create XML on string level (as I do it in the final SELECT like SELECT '<' + innerNvp.Name + '>' +, but it is a working possibility to deal with column names dynamically. Otherwise you'd either have to know all columns in advance, or you'd need to go the path of dynamic SQL with EXEC. There's one thing to keep in mind: The names in your structure (like "name" must be valid XML-tag-names.
one general hint: All approaches here try to cut your parts on string level. This might break, if there is a } or a ," or a : in an unexpected place...
DECLARE #str NVARCHAR(MAX)='{"name":"daniel & sophia","age":20,"year":2009,"weigth":15.1,"points":3,"alias":"dani,da"}{"name":"charls & lina","age":22,"year":2009,"weigth":15.1,"points":3,"alias":"carlos,lini"}';
WITH SplittedAtClosingCurly AS
(
SELECT CAST('<x>' + REPLACE((SELECT #str AS [*] FOR XML PATH('')),'}','</x><x>') + '</x>' AS XML) AS TheRows
)
,SplittedAtCommaQuote AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNr
,CAST('<x>' + REPLACE((SELECT Rw.value(N'text()[1]','nvarchar(max)') AS [*] FOR XML PATH('')),',"','</x><x>') + '</x>' AS XML) AS TheRow
FROM SplittedAtClosingCurly
CROSS APPLY TheRows.nodes(N'/x[text()]') AS A(Rw)
)
,SplittedAtDoubleDot AS
(
SELECT RowNr
,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS TplNr
,CAST('<x>' + REPLACE((SELECT Tpl.value(N'text()[1]','nvarchar(max)') AS [*] FOR XML PATH('')),':','</x><x>') + '</x>' AS XML) AS TheTupel
FROM SplittedAtCommaQuote
CROSS APPLY TheRow.nodes(N'/x[text()]') AS A(Tpl)
)
,DerivedTable_NameValuePairs AS
(
SELECT RowNr
,TplNr
,REPLACE(REPLACE(TheTupel.value(N'/x[1]/text()[1]','nvarchar(max)'),'{',''),'"','') AS Name
,REPLACE(REPLACE(TheTupel.value(N'/x[2]/text()[1]','nvarchar(max)'),'{',''),'"','') AS Value
FROM SplittedAtDoubleDot
)
SELECT CAST(
(
SELECT '<' + innerNvp.Name + '>' + (SELECT innerNvp.Value AS [*] FOR XML PATH('')) + '</' + innerNvp.Name + '>'
FROM DerivedTable_NameValuePairs AS innerNvp
WHERE innerNvp.RowNr=nvp.RowNr
ORDER BY TplNr
FOR XML PATH(''),TYPE
).value(N'text()[1]','nvarchar(max)') AS XML)
FROM DerivedTable_NameValuePairs AS nvp
GROUP BY RowNr
FOR XML PATH('participant'),ROOT('participants')
This query returns an equivalent attribute-type xml like this
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #tmp
CREATE TABLE #tmp
(
Id INT IDENTITY,
Campo VARCHAR(MAX)
)
INSERT INTO #tmp
(
Campo
)
VALUES
(
'{"name":"daniel & sophia","age":20,"year":2009,"weigth":15.1,"points":3,"alias":"dani,da"}{"name":"charls & lina","age":22,"year":2009,"weigth":15.1,"points":3,"alias":"carlos,lini"}'
)
SELECT (select (CAST(replace(replace(replace(replace(replace(replace(
replace(replace(Replace(t.Campo, '{"', '<participant '), '"}','" />'), '":"', '":'),'","',',"')
, '":', '":"'),',"','","'), '":"', '="'), '","', '" '), '&',',') AS XML)
)
FOR XML PATH (''), ROOT ('participants')) as xml
FROM #tmp t
& is illegal in xml, then i replaced it with ,.
Result:
<participants>
<participant name="daniel , sophia" age="20" year="2009" weigth="15.1" points="3" alias="dani,da"/>
<participant name="charls , lina" age="22" year="2009" weigth="15.1" points="3" alias="carlos,lini"/>
</participants>
** -- Updated for Updated Question --**
With the help of a Parse/Split UDF. Just about any Parse/Split UDF would do the trick. I did however supply mine.
This approach can be applied to any portion of your core data.
Example
Declare #YourTable table (ID int,Campo varchar(max))
Insert Into #YourTable values
(1,'{"name":"daniel & sophia","age":20,"year":2009,"weight":15.1,"points":3,"alias":"dani,da"}{"name":"charls & lina","age":22,"year":2007,"weight":19.0"points":3,"alias":"carlos,lini"}')
Select [name] = max(case when Item='name' then Value end)
,[age] = max(case when Item='age' then Value end)
,[year] = max(case when Item='year' then Value end)
,[weight] = max(case when Item='weight' then Value end)
,[points] = max(case when Item='points' then Value end)
,[alias] = max(case when Item='alias' then Value end)
From (
Select A.ID
,RowNr = B.RetSeq
,Item = replace(replace(left(C.RetVal,charindex(':',C.RetVal)-1),'"',''),'{','')
,Value = replace(replace(right(C.RetVal,len(C.RetVal)-charindex(':',C.RetVal)),'"',''),'}','')
From #YourTable A
Cross Apply [dbo].[udf-Str-Parse](A.Campo,'}{') B -- NOTE: Should really be },{
Cross Apply [dbo].[udf-Str-Parse](B.RetVal,',"') C
-- YOUR WHERE STATEMENT HERE
) A
Group By ID,RowNr
Order By ID,RowNr
For XML Path('participant'),Root('participants'),Type
Returns
<participants>
<participant>
<name>daniel & sophia</name>
<age>20</age>
<year>2009</year>
<weight>15.1</weight>
<points>3</points>
<alias>dani,da</alias>
</participant>
<participant>
<name>charls & lina</name>
<age>22</age>
<year>2007</year>
<weight>19.0points:3</weight>
<alias>carlos,lini</alias>
</participant>
</participants>
The UDF if Interested
CREATE FUNCTION [dbo].[udf-Str-Parse] (#String varchar(max),#Delimiter varchar(10))
Returns Table
As
Return (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace(#String,#Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
--Thanks Shnugo for making this XML safe
--Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
--Select * from [dbo].[udf-Str-Parse]('this,is,<test>,for,< & >',',')
One final note:
If you can't use or want an UDF, this can easily be converted to in-line.
EDIT - In-line Approach
Select [name] = max(case when Item='name' then Value end)
,[age] = max(case when Item='age' then Value end)
,[year] = max(case when Item='year' then Value end)
,[weight] = max(case when Item='weight' then Value end)
,[points] = max(case when Item='points' then Value end)
,[alias] = max(case when Item='alias' then Value end)
From (
Select A.ID
,RowNr = B.RetSeq
,Item = replace(replace(left(C.RetVal,charindex(':',C.RetVal)-1),'"',''),'{','')
,Value = replace(replace(right(C.RetVal,len(C.RetVal)-charindex(':',C.RetVal)),'"',''),'}','')
From YourTable A
Cross Apply (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace(A.Campo,'}{','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) B
Cross Apply (
Select RetSeq = Row_Number() over (Order By (Select null))
,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace(B.RetVal,',"','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
) C
-- Your WHERE STATEMENT here --
) A
Group By ID,RowNr
Order By ID,RowNr
For XML Path('participant'),Root('participants'),Type
I add this as a new answer, it is an addition to TriV's answer actually:
The transformation to attribute centered XML is a good idea. You might go one step further with a FLWOR XQuery approach:
DECLARE #xml XML=
N'<participants>
<participant name="daniel & sophia" age="20" year="2009" weigth="15.1" points="3" alias="dani,da"/>
<participant name="charls & lina" age="22" year="2009" weigth="15.1" points="3" alias="carlos,lini"/>
</participants>';
SELECT #xml.query
('
<participants>
{
for $p in /participants/participant
return
<participant>
{
for $attr in $p/#*
return <data name="{local-name($attr)}" value="{string($attr)}"/>
}
</participant>
}
</participants>
');
The result
<participants>
<participant>
<data name="name" value="daniel & sophia" />
<data name="age" value="20" />
<data name="year" value="2009" />
<data name="weigth" value="15.1" />
<data name="points" value="3" />
<data name="alias" value="dani,da" />
</participant>
<participant>
<data name="name" value="charls & lina" />
<data name="age" value="22" />
<data name="year" value="2009" />
<data name="weigth" value="15.1" />
<data name="points" value="3" />
<data name="alias" value="carlos,lini" />
</participant>
</participants>
Regrettfully this approach does not support dynamically created elements.
UPDATE: Slightly different, even closer:
The following query will place the values as element's text(), while the element's name is still an attribute...
SELECT #xml.query
('
<participants>
{
for $p in /participants/participant
return
<participant>
{
for $attr in $p/#*
return <data name="{local-name($attr)}">{string($attr)}</data>
}
</participant>
}
</participants>');
The result
<participants>
<participant>
<data name="name">daniel & sophia</data>
<data name="age">20</data>
<data name="year">2009</data>
<data name="weigth">15.1</data>
<data name="points">3</data>
<data name="alias">dani,da</data>
</participant>
<participant>
<data name="name">charls & lina</data>
<data name="age">22</data>
<data name="year">2009</data>
<data name="weigth">15.1</data>
<data name="points">3</data>
<data name="alias">carlos,lini</data>
</participant>
</participants>

ORA-19228: XPST0008 - undeclared identifier in oracle sql

I have xml string which i have mentioned below and i want to extract code from xml string. I have written below select query to extract the value from <ax2140:code>0</ax2140:code> which is 0 but i am getting error as
ORA-19228: XPST0008 - undeclared identifier: prefix 'ax2140' local-name 'ax2140:code'
19228. 00000 - "XPST0008 - undeclared identifier: prefix '%s' local-name '%s'"
Here is my xml string-
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:placeShopOrderResponse xmlns:ns="http://service.soap.CDRator.com">
<ns:return xmlns:ax2127="http://data.soap.CDRator.com/xsd"
xmlns:ax2129="http://webshop.data.soap.CDRator.com/xsd"
xmlns:ax2130="http://core.data.soap.CDRator.com/xsd"
xmlns:ax2133="http://signup.data.soap.CDRator.com/xsd"
xmlns:ax2134="http://core.signup.data.soap.CDRator.com/xsd"
xmlns:ax2139="http://result.service.soap.CDRator.com/xsd"
xmlns:ax2140="http://core.result.service.soap.CDRator.com/xsd"
xmlns:ax2147="http://webshop.result.service.soap.CDRator.com/xsd"
xmlns:ax2148="http://mandate.result.service.soap.CDRator.com/xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax2147:PlaceShopOrderResultDTO">
<ax2130:id xsi:nil="true" />
<ax2140:code>0</ax2140:code>
<ax2140:description>OK</ax2140:description>
<ax2127:statusId>1</ax2127:statusId>
<ax2127:subscriptionCondition xsi:type="ax2127:SubscriptionStatusDTO">
<ax2130:id xsi:nil="true" />
<ax2140:code>0</ax2140:code>
<ax2140:description>OK</ax2140:description>
<ax2130:imsi xsi:nil="true" />
<ax2130:phoneNumber>NO_NUMBER</ax2130:phoneNumber>
<ax2127:imei xsi:nil="true" />
<ax2127:simCard xsi:nil="true" />
</ax2127:teleService>
</ax2147:subscriptions>
</ns:return>
</ns:placeShopOrderResponse>
</soapenv:Body>
</soapenv:Envelope>
Here is my select query:
SELECT ID,xt_code.CODE
FROM TEMP_SOAP_MONITORING_MSP sm
CROSS JOIN XMLTable(XMLNAMESPACES (
'http://core.result.service.soap.CDRator.com/xsd' as "ax2140_code"
),
'for $i in //ax2140:code return $i'
passing XMLType(sm.RESPONSE_XML)
columns "CODE" VARCHAR2(50) path '/') xt_code;
Use "ax2140" instead of "ax2140_code" in the query.

how to get xsd element format result from sql script

I need to create xml files to migrate a huge amount of data from one database to another database.
How to get result xsd format as below from ms sql script query?
Please share if you have any idea.
The xml file format is below:
<Batch>
<retail:customer xmlns:core="http://www.bactor.com/core" xmlns:retail=""http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:addresses>
<retail:address>
<retail:country>GB</retail:country>
<retail:countryCodeId></retail:countryCodeId>
<retail:isPreferred>true</retail:isPreferred>
<retail:isActive>true</retail:isActive>
<retail:typeId>PERSONAL_ADDRESS</retail:typeId>
<retail:postCode>2344</retail:postCode>
<retail:street1>1234214</retail:street1>
<retail:isTemplate>false</retail:isTemplate>
<retail:referenceId></retail:referenceId>
<retail:addressReferenceId>0727-:83f5bd9f331:e8e438a1:fa34668911272008</retail:addressReferenceId>
</retail:address>
</retail:addresses>
<retail:contactMethod></retail:contactMethod>
<retail:contactable>false</retail:contactable>
<retail:maritalStatus></retail:maritalStatus>
<retail:nationality></retail:nationality>
<retail:noChildren>0</retail:noChildren>
<retail:customerNumber>1</retail:customerNumber>
<retail:emailAddresses>
<retail:emailAddress>alice#wonderland.hearts</retail:emailAddress>
<retail:preferred>true</retail:preferred>
<retail:restrictedReason></retail:restrictedReason>
<retail:status></retail:status>
<retail:typeId>PERSONAL_EMAIL</retail:typeId>
<retail:referenceId></retail:referenceId>
<retail:active>false</retail:active>
</retail:emailAddresses>
<retail:phoneNumbers>
<retail:countryCode></retail:countryCode>
<retail:number>11222445566</retail:number>
<retail:preferred>true</retail:preferred>
<retail:restrictedReason></retail:restrictedReason>
<retail:status></retail:status>
<retail:typeId>LANDLINE</retail:typeId>
<retail:referenceId></retail:referenceId>
<retail:active>true</retail:active>
<retail:phoneNumberReferenceId>e437-:83f5bd9f331:e8e438a1:fa34668911272008</retail:phoneNumberReferenceId>
</retail:phoneNumbers>
<retail:customerName>
<retail:surname>AppleGate</retail:surname>
<retail:forename>Alice</retail:forename>
<retail:title>Mrs</retail:title>
<retail:sex>FEMALE</retail:sex>
<retail:dateOfBirth>2012-09-12T00:00:00+01:00</retail:dateOfBirth>
</retail:customerName>
<retail:businessContactMethod></retail:businessContactMethod>
<retail:preferredContactTime></retail:preferredContactTime>
<retail:allowInternalMarketing>true</retail:allowInternalMarketing>
<retail:allowExternalMarketing>true</retail:allowExternalMarketing>
<retail:employeeKey></retail:employeeKey>
<retail:customerType>RETAIL</retail:customerType>
<retail:organisation></retail:organisation>
<retail:taxIdentification></retail:taxIdentification>
<retail:companyNumber></retail:companyNumber>
<retail:createdBy></retail:createdBy>
<retail:createdAt></retail:createdAt>
<retail:status>New</retail:status>
<retail:source></retail:source>
</retail:customer>
<retail:customer xmlns:core="http://www.enactor.com/core" xmlns:retail="http://www.enactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:addresses>
<retail:address>
<retail:country>GB</retail:country>
<retail:countryCodeId></retail:countryCodeId>
<retail:isPreferred>true</retail:isPreferred>
<retail:isActive>true</retail:isActive>
<retail:typeId>PERSONAL_ADDRESS</retail:typeId>
<retail:postCode>2344</retail:postCode>
<retail:street1>1234214</retail:street1>
<retail:isTemplate>false</retail:isTemplate>
<retail:referenceId></retail:referenceId>
<retail:addressReferenceId>0727-:83f5bd9f331:e8e438a1:fa34668911272008</retail:addressReferenceId>
</retail:address>
</retail:addresses>
<retail:contactMethod></retail:contactMethod>
<retail:contactable>false</retail:contactable>
<retail:maritalStatus></retail:maritalStatus>
<retail:nationality></retail:nationality>
<retail:noChildren>0</retail:noChildren>
<retail:customerNumber>1</retail:customerNumber>
<retail:emailAddresses>
<retail:emailAddress>alice#wonderland.hearts</retail:emailAddress>
<retail:preferred>true</retail:preferred>
<retail:restrictedReason></retail:restrictedReason>
<retail:status></retail:status>
<retail:typeId>PERSONAL_EMAIL</retail:typeId>
<retail:referenceId></retail:referenceId>
<retail:active>false</retail:active>
</retail:emailAddresses>
<retail:phoneNumbers>
<retail:countryCode></retail:countryCode>
<retail:number>11222445566</retail:number>
<retail:preferred>true</retail:preferred>
<retail:restrictedReason></retail:restrictedReason>
<retail:status></retail:status>
<retail:typeId>LANDLINE</retail:typeId>
<retail:referenceId></retail:referenceId>
<retail:active>true</retail:active>
<retail:phoneNumberReferenceId>e437-:83f5bd9f331:e8e438a1:fa34668911272008</retail:phoneNumberReferenceId>
</retail:phoneNumbers>
<retail:customerName>
<retail:surname>AppleGate</retail:surname>
<retail:forename>Alice</retail:forename>
<retail:title>Mrs</retail:title>
<retail:sex>FEMALE</retail:sex>
<retail:dateOfBirth>2012-09-12T00:00:00+01:00</retail:dateOfBirth>
</retail:customerName>
<retail:businessContactMethod></retail:businessContactMethod>
<retail:preferredContactTime></retail:preferredContactTime>
<retail:allowInternalMarketing>true</retail:allowInternalMarketing>
<retail:allowExternalMarketing>true</retail:allowExternalMarketing>
<retail:employeeKey></retail:employeeKey>
<retail:customerType>RETAIL</retail:customerType>
<retail:organisation></retail:organisation>
<retail:taxIdentification></retail:taxIdentification>
<retail:companyNumber></retail:companyNumber>
<retail:createdBy></retail:createdBy>
<retail:createdAt></retail:createdAt>
<retail:status>New</retail:status>
<retail:source></retail:source>
</retail:customer>
</Batch>
I am also trying with the below a pieces of sql script. but it is not working.
WITH XMLNAMESPACES ('http://www.enactor.com/retail' as ns1)
SELECT top 100 [id]
,[Title]
,[First_Name]
, RowNum = Row_NUMBER() OVER (Order by id)
FROM [Firinne].[dbo].[Contact] as Customer
For XML PATH('retail:Customer')
Try this:
DECLARE #xml XML
;WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi, 'http://www.bactor.com/retail' AS retail, 'http://www.bactor.com/core' AS core)
SELECT #xml = (SELECT
[retail:Customer].id AS [retail:id],
[retail:Customer].contactMethod AS [retail:contactMethod],
[retail:Customer].contactable AS [retail:contactable],
[retail:address].emailAddress AS [retail:emailAddress],
[retail:address].typeId AS [retail:typeId]
FROM dbo.Customers AS [retail:Customer]
JOIN dbo.emailAddresses AS [retail:address] ON [retail:Customer].id = [retail:address].customerID
FOR XML AUTO, ELEMENTS)
SET #xml = '<Batch>' + CAST(#xml AS NVARCHAR(max)) + '</Batch>'
SELECT #xml
Output:
<Batch>
<retail:Customer xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:id>1</retail:id>
<retail:contactMethod>1</retail:contactMethod>
<retail:contactable>1</retail:contactable>
<retail:address>
<retail:emailAddress>some#some.some</retail:emailAddress>
<retail:typeId>1</retail:typeId>
</retail:address>
<retail:address>
<retail:emailAddress>some#some.some</retail:emailAddress>
<retail:typeId>2</retail:typeId>
</retail:address>
</retail:Customer>
<retail:Customer xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:id>2</retail:id>
<retail:contactMethod>1</retail:contactMethod>
<retail:contactable>0</retail:contactable>
<retail:address>
<retail:emailAddress>some#some.some</retail:emailAddress>
<retail:typeId>3</retail:typeId>
</retail:address>
</retail:Customer>
</Batch>
EDIT:
You can do it like:
DECLARE #xml XML
;WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi, 'http://www.bactor.com/retail' AS retail, 'http://www.bactor.com/core' AS core)
SELECT #xml = (SELECT
[retail:Customer].id AS [retail:id],
[retail:Customer].contactMethod AS [retail:contactMethod],
[retail:Customer].contactable AS [retail:contactable],
(SELECT
[retail:address].emailAddress ,
[retail:address].typeId
FROM dbo.emailAddresses AS [retail:address] WHERE [retail:Customer].id = [retail:address].customerID
FOR XML AUTO, TYPE, ELEMENTS, ROOT('retail:Addresses')
)
FROM dbo.Customers AS [retail:Customer]
FOR XML AUTO, ELEMENTS)
SET #xml = '<Batch>' + CAST(#xml AS NVARCHAR(max)) + '</Batch>'
SELECT #xml
But namespaces are added to all child:
<Batch>
<retail:Customer xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:id>1</retail:id>
<retail:contactMethod>1</retail:contactMethod>
<retail:contactable>1</retail:contactable>
<retail:Addresses xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:address>
<emailAddress>some#some.some</emailAddress>
<typeId>1</typeId>
</retail:address>
<retail:address>
<emailAddress>some#some.some</emailAddress>
<typeId>2</typeId>
</retail:address>
</retail:Addresses>
</retail:Customer>
<retail:Customer xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:id>2</retail:id>
<retail:contactMethod>1</retail:contactMethod>
<retail:contactable>0</retail:contactable>
<retail:Addresses xmlns:core="http://www.bactor.com/core" xmlns:retail="http://www.bactor.com/retail" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<retail:address>
<emailAddress>some#some.some</emailAddress>
<typeId>3</typeId>
</retail:address>
</retail:Addresses>
</retail:Customer>
</Batch>
It is a known issue, and you can see details here:
https://connect.microsoft.com/SQLServer/feedback/details/265956/suppress-namespace-attributes-in-nested-select-for-xml-statements
Additional namespaces doesn't do any harm but increasing size of generated xml document.