Der veraltete Ansatz mit FROM OPENXML
wäre hier vielleicht eine Option. Überprüfen Sie diese Antwort
.
Unter diesem Link Sie werden von Zeit zu Zeit eine Funktion finden, die John Cappelletti gepostet hat und die jegliches XML schreddert (Quellenangabe unter dem Code der Funktion).
Aber ich bin mir nicht sicher, was Sie wirklich erreichen wollen ... Warum brauchen Sie den Pfad? Wenn Sie an den Werten aller Zielknoten interessiert sind, können Sie so etwas tun (tiefe Suche mit //
benötigt nicht den genauen XPath
)
SELECT t.value(N'(text())[1]','nvarchar(max)')
FROM @xml.nodes('//target') AS A(t);
Wenn Sie wirklich alles und alles brauchen Sie können dies überprüfen:
CREATE FUNCTION [dbo].[udf-XML-Hier](@XML xml)
Returns Table
As Return
with cte0 as (
Select Lvl = 1
,ID = Cast(1 as int)
,Pt = Cast(NULL as int)
,Element = x.value('local-name(.)','varchar(150)')
,Attribute = cast('' as varchar(150))
,Value = x.value('text()[1]','varchar(max)')
,XPath = cast(concat(x.value('local-name(.)','varchar(max)'),'[' ,cast(Row_Number() Over(Order By (Select 1)) as int),']') as varchar(max))
,Seq = cast(1000000+Row_Number() over(Order By (Select 1)) as varchar(max))
,AttData = x.query('.')
,XMLData = x.query('*')
From @XML.nodes('/*') a(x)
Union All
Select Lvl = p.Lvl + 1
,ID = Cast( (Lvl + 1) * 1024 + (Row_Number() Over(Order By (Select 1)) * 2) as int ) * 10
,Pt = p.ID
,Element = c.value('local-name(.)','varchar(150)')
,Attribute = cast('' as varchar(150))
,Value = cast( c.value('text()[1]','varchar(max)') as varchar(max) )
,XPath = cast(concat(p.XPath,'/',c.value('local-name(.)','varchar(max)'),'[',cast(Row_Number() Over(PARTITION BY c.value('local-name(.)','varchar(max)') Order By (Select 1)) as int),']') as varchar(max) )
,Seq = cast(concat(p.Seq,' ',10000000+Cast( (Lvl + 1) * 1024 + (Row_Number() Over(Order By (Select 1)) * 2) as int ) * 10) as varchar(max))
,AttData = c.query('.')
,XMLData = c.query('*')
From cte0 p
Cross Apply p.XMLData.nodes('*') b(c)
)
, cte1 as (
Select R1 = Row_Number() over (Order By Seq),A.*
From (
Select Lvl,ID,Pt,Element,Attribute,Value,XPath,Seq From cte0
Union All
Select Lvl = p.Lvl+1
,ID = p.ID + Row_Number() over (Order By (Select NULL))
,Pt = p.ID
,Element = p.Element
,Attribute = x.value('local-name(.)','varchar(150)')
,Value = x.value('.','varchar(max)')
,XPath = p.XPath + '/@' + x.value('local-name(.)','varchar(max)')
,Seq = cast(concat(p.Seq,' ',10000000+p.ID + Row_Number() over (Order By (Select NULL)) ) as varchar(max))
From cte0 p
Cross Apply AttData.nodes('/*/@*') a(x)
) A
)
Select A.R1
,R2 = IsNull((Select max(R1) From cte1 Where Seq Like A.Seq+'%'),A.R1)
,A.Lvl
,A.ID
,A.Pt
,A.Element
,A.Attribute
,A.XPath
,Title = Replicate('|---',Lvl-1)+Element+IIF(Attribute='','','@'+Attribute)
,A.Value
From cte1 A
/*
Source: http://beyondrelational.com/modules/2/blogs/28/posts/10495/xquery-lab-58-select-from-xml.aspx
Taken from John Cappelletti: https://stackoverflow.com/a/42729851/5089204
Declare @XML xml='<person><firstname preferred="Annie" nickname="BeBe">Annabelle</firstname><lastname>Smith</lastname></person>'
Select * from [dbo].[udf-XML-Hier](@XML) Order by R1
*/
GO
DECLARE @xml XML=
'<log>
<clients>
<client>
<section name ="Apps">
<questions>
<groupone>
<question>
<target>Age</target>
</question>
<question>
<target> Height</target>
</question>
<question>
<target> Weight</target>
</question>
</groupone>
<grouptwo name = "exercise">
<wording>what is your name</wording>
<question>
<id>1</id>
<target>def</target>
</question>
</grouptwo>
</questions>
</section>
</client>
</clients>
</log>';
SELECT * FROM dbo.[udf-XML-Hier](@xml);
GO