DECLARE @XML1 XML =
'<sender id="1" operation="NewValue" LastName="XYZ" loginId="10029" />
<sender id="2" operation="OldValue" LastName="PQR" loginId="10029" />'
SELECT T.C.value('local-name(.)', 'varchar(50)') AS NodeName,
T.C.value('(.)[1]', 'varchar(50)') AS NodeValue
FROM @xml1.nodes('//*') AS T(C)
又一个例子
DECLARE @xml XML =
'<row>
<operation>NewValue</operation>
<LastName>Gandhi</LastName>
<loginId>1011</loginId>
</row>
<row>
<operation>OldValue</operation>
<LastName>Gandhi</LastName>
<loginId>1010</loginId>
</row>'
SELECT T.C.value('local-name(.)', 'varchar(50)') AS NodeName,
T.C.value('(.)[1]', 'varchar(50)') AS NodeValue
FROM @xml.nodes('row/*') AS T(C)
WHERE T.C.value('(//row/operation/text())[1]', 'VARCHAR(20)') = 'NewValue'
(我希望获得类似此查询的结果,但我的XML格式不同)。
答案 0 :(得分:1)
这是 - 当然! - 错误的做法。没有 I-read-any-XML-no-matter-what-structure-it-may-have -solution。
请看下面的内容,但是要仔细看看第三个例子:
DECLARE @dummy TABLE(ID INT IDENTITY,Comment VARCHAR(100),YourXML XML);
INSERT INTO @dummy VALUES
('Your sample 1'
,N'<sender id="1" operation="NewValue" LastName="XYZ" loginId="10029" />
<sender id="2" operation="OldValue" LastName="PQR" loginId="10029" />')
,('Your sample 2'
,N'<row>
<operation>NewValue</operation>
<LastName>Gandhi</LastName>
<loginId>1011</loginId>
</row>
<row>
<operation>OldValue</operation>
<LastName>Gandhi</LastName>
<loginId>1010</loginId>
</row>')
,('Show the limits'
,N'<row>
<element name="test">all have</element>
<element name="other">the local-name()</element>
<element name="One more">element</element>
</row>');
SELECT ID
,Comment
,'Element' AS ElementType
,t.x.value('local-name(..)','nvarchar(max)') AS ElementName
,t.x.value('.','nvarchar(max)') AS ElementValue
FROM @dummy AS d
CROSS APPLY d.YourXML.nodes(N'//*/text()') AS t(x)
UNION ALL
SELECT ID
,Comment
,'Attribute'
,t.a.value('local-name(.)','nvarchar(max)') AS ElementName
,t.a.value('.','nvarchar(max)') AS ElementValue
FROM @dummy AS d
CROSS APPLY d.YourXML.nodes(N'//*/@*') AS t(a)
答案 1 :(得分:1)
Shnugo (在另一篇文章中)建议发布一个Table-Valued-Function,用于解析几乎任何XML结构。我应该添加性能是可敬的(示例1为90 ms),但原生XML会更有效。
原始来源是:http://beyondrelational.com/modules/2/blogs/28/posts/10495/xquery-lab-58-select-from-xml.aspx我只做了一些调整。
示例1
Declare @XML xml ='
<row>
<operation>NewValue</operation>
<LastName>Gandhi</LastName>
<loginId>1011</loginId>
</row>
<row>
<operation>OldValue</operation>
<LastName>Gandhi</LastName>
<loginId>1010</loginId>
</row>'
Select * from [dbo].[udf-XML-Hier](@XML) Order by R1
<强>返回强>
示例2
Declare @XML1 xml = '
<sender id="1" operation="NewValue" LastName="XYZ" loginId="10029" />
<sender id="2" operation="OldValue" LastName="PQR" loginId="10029" />
'
Select * from [dbo].[udf-XML-Hier](@XML1) Order By 1
<强>返回强>
感兴趣的UDF
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
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
*/