Solution via openxml.
declare @idoc int, @doc varchar(max);
set @doc =
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<genRetrieve xmlns:v1="http://xxxxxxxxxxxxxxxxxxxxx">
<checkRetrieve>
<party>
<user>
<first>BLA</first>
<last>last</last>
</user>
<media>none</media>
</party>
</checkRetrieve>
</genRetrieve>
</soapenv:Body>
</soapenv:Envelope>'
exec sp_xml_preparedocument @idoc output, @doc;
;with map as (
select *
from openxml (@idoc, '//*')
), rcte as (
select localname, parentid, '/' + isnull (prefix + ':', '') + localname as XPATH
from openxml (@idoc, '//*[text()]')
where nodetype = 1 and [text] is not null -- localname <> '#text'
union all
select r.localname, m.parentid, '/' + isnull (prefix + ':', '') + m.localname + XPATH
from rcte r
inner join map m on r.parentid = m.id
)
select localname as [TEXT NODE], XPATH
from rcte
where parentid is null;
exec sp_xml_removedocument @idoc;
UPD. Solution with nodes numeration.
exec sp_xml_preparedocument @idoc output, @doc;
;with map as (
select id, parentid, nodetype, localname, prefix, row_number() over(partition by parentid, prefix, localname order by id) as num
from openxml (@idoc, '//*')
where nodetype = 1 or (nodetype = 3 and [text] is not null)
), rcte as (
select p.localname, p.parentid, '/' + isnull (p.prefix + ':', '') + p.localname + '[' + cast (p.num as varchar(50)) + ']' as XPATH
from map c
inner join map p on c.parentid = p.id
where c.nodetype = 3
union all
select r.localname, m.parentid, '/' + isnull (prefix + ':', '') + m.localname + '[' + cast (m.num as varchar(50)) + ']' + XPATH
from rcte r
inner join map m on r.parentid = m.id
)
select localname as [TEXT NODE], XPATH
from rcte
where parentid is null;
exec sp_xml_removedocument @idoc;
UPD 2. Yet another solution showing VALUE and nodes without text.
exec sp_xml_preparedocument @idoc output, @doc;
;with map as (
select id, parentid, nodetype, localname, prefix, [text]
, row_number() over(partition by parentid, prefix, localname order by id) as num
from openxml (@idoc, '//*')
where nodetype = 1 or (nodetype = 3 and [text] is not null)
)
, rcte as (
select localname, parentid, '/' + isnull (prefix + ':', '') + localname + '[' + cast (num as varchar(50)) + ']' as XPATH, VALUE
from (
select p.localname, p.parentid, p.prefix, p.num
, min (c.nodetype) as min_nodetype
, min (case when c.nodetype = 3 then cast (c.[text] as nvarchar(max)) end) as VALUE
from map p
left join map c on p.id = c.parentid
where p.nodetype = 1
group by p.localname, p.parentid, p.prefix, p.num
) t
where min_nodetype = 3 or min_nodetype is null
union all
select r.localname, m.parentid, '/' + isnull (prefix + ':', '') + m.localname + '[' + cast (m.num as varchar(50)) + ']' + XPATH, VALUE
from rcte r
inner join map m on r.parentid = m.id
)
select localname as [TEXT NODE], XPATH, VALUE
from rcte
where parentid is null;
exec sp_xml_removedocument @idoc;