用于提取元素属性的循环 XML
Loop for extracting attributes of elements XML
我需要从一长串各种元素中提取所有属性。因此,我正在寻求构建一个遍历我的所有元素和 return 它们的属性的循环。
通过几篇文章,我已经能够编写下面的代码。但是,我有超过 1000 个元素,如果能够以某种方式围绕后一部分构建一个循环而不是为所有元素复制它,我会非常高兴。
with cte as
(
select cast(
'<schema fwRel="2">
<taxFormId isPrimeKey="true" fkRef="C1-TXFRM" mapField="TAX_FORM_ID" dataType="string"/>
<formType fkRef="C1-FRMTY" mapField="FORM_TYPE_CD" dataType="string"/>
<bo suppress="true" required="true" fkRef="F1-BUSOB" mapField="BUS_OBJ_CD" dataType="string"/>
<transferReason mdField="C1_TXF_TFRRSN_FLG" dataType="lookup" mapXML="BO_DATA_AREA" lookup="C1_TXF_TFRRSN_FLG"/>
</schema>' as xml) xml_col
)
select cte.xml_col.value('(/schema/taxFormId/@fkRef)[1]', 'varchar(100)') as Dummy1
cte.xml_col.value('(/schema/taxFormId/@mapField)[1]', 'varchar(100)') as Dummy2
cte.xml_col.value('(/schema/taxFormId/@dataType)[1]', 'varchar(100)') as Dummy3
cte.xml_col.value('(/schema/taxFormId/@mapXML)[1]', 'varchar(100)') as Dummy4
from cte
希望我提供了足够的信息
可能有点over-kill,但我经常使用 TVF 来解析和散列大型 XML 文件。该函数将 return 具有范围键 R1/R2.
的 parent/child 层次结构中的数据
例如:
Declare @XML xml='
<schema fwRel="2">
<taxFormId isPrimeKey="true" fkRef="C1-TXFRM" mapField="TAX_FORM_ID" dataType="string"/>
<formType fkRef="C1-FRMTY" mapField="FORM_TYPE_CD" dataType="string"/>
<bo suppress="true" required="true" fkRef="F1-BUSOB" mapField="BUS_OBJ_CD" dataType="string"/>
<transferReason mdField="C1_TXF_TFRRSN_FLG" dataType="lookup" mapXML="BO_DATA_AREA" lookup="C1_TXF_TFRRSN_FLG"/>
</schema>'
Select * from [dbo].[udf-XML-Hier](@XML) Order by R1
Returns
您会注意到元素名称、属性名称、XPath、标题(可选)和值列。 R1,R2,Lvl,ID,PT都是派生出来的
作为 TVF,您可以申请任何 WHERE
或 ORDER
所需的
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(10000001 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
*/
获取属性列表的简单方法:
with cte as
(
select cast(
'<schema fwRel="2">
<taxFormId isPrimeKey="true" fkRef="C1-TXFRM" mapField="TAX_FORM_ID" dataType="string" />
<formType fkRef="C1-FRMTY" mapField="FORM_TYPE_CD" dataType="string" />
<bo suppress="true" required="true" fkRef="F1-BUSOB" mapField="BUS_OBJ_CD" dataType="string" />
<transferReason mdField="C1_TXF_TFRRSN_FLG" dataType="lookup" mapXML="BO_DATA_AREA" lookup="C1_TXF_TFRRSN_FLG" />
</schema>' as xml) xml_col
)
--查询使用.nodes(N'/schema/*')
列出<schema>
下方的所有节点,使用.nodes(N'@*')
列出该节点内的所有属性:
select nd.value(N'local-name(.)',N'nvarchar(max)') AS NodeName
,attr.value(N'local-name(.)',N'nvarchar(max)') AS AttrName
,attr.value(N'.',N'nvarchar(max)') AS AttrValue
from cte
OUTER APPLY xml_col.nodes(N'/schema/*') AS A(nd)
OUTER APPLY A.nd.nodes(N'@*') AS B(attr)
结果:
taxFormId isPrimeKey true
taxFormId fkRef C1-TXFRM
taxFormId mapField TAX_FORM_ID
taxFormId dataType string
formType fkRef C1-FRMTY
formType mapField FORM_TYPE_CD
formType dataType string
bo suppress true
bo required true
bo fkRef F1-BUSOB
bo mapField BUS_OBJ_CD
bo dataType string
transferReason mdField C1_TXF_TFRRSN_FLG
transferReason dataType lookup
transferReason mapXML BO_DATA_AREA
transferReason lookup C1_TXF_TFRRSN_FLG
如果您需要像示例中那样的语句,可以动态创建它(作为字符串)并使用 EXEC
执行此语句(动态 SQL).
我需要从一长串各种元素中提取所有属性。因此,我正在寻求构建一个遍历我的所有元素和 return 它们的属性的循环。
通过几篇文章,我已经能够编写下面的代码。但是,我有超过 1000 个元素,如果能够以某种方式围绕后一部分构建一个循环而不是为所有元素复制它,我会非常高兴。
with cte as
(
select cast(
'<schema fwRel="2">
<taxFormId isPrimeKey="true" fkRef="C1-TXFRM" mapField="TAX_FORM_ID" dataType="string"/>
<formType fkRef="C1-FRMTY" mapField="FORM_TYPE_CD" dataType="string"/>
<bo suppress="true" required="true" fkRef="F1-BUSOB" mapField="BUS_OBJ_CD" dataType="string"/>
<transferReason mdField="C1_TXF_TFRRSN_FLG" dataType="lookup" mapXML="BO_DATA_AREA" lookup="C1_TXF_TFRRSN_FLG"/>
</schema>' as xml) xml_col
)
select cte.xml_col.value('(/schema/taxFormId/@fkRef)[1]', 'varchar(100)') as Dummy1
cte.xml_col.value('(/schema/taxFormId/@mapField)[1]', 'varchar(100)') as Dummy2
cte.xml_col.value('(/schema/taxFormId/@dataType)[1]', 'varchar(100)') as Dummy3
cte.xml_col.value('(/schema/taxFormId/@mapXML)[1]', 'varchar(100)') as Dummy4
from cte
希望我提供了足够的信息
可能有点over-kill,但我经常使用 TVF 来解析和散列大型 XML 文件。该函数将 return 具有范围键 R1/R2.
的 parent/child 层次结构中的数据例如:
Declare @XML xml='
<schema fwRel="2">
<taxFormId isPrimeKey="true" fkRef="C1-TXFRM" mapField="TAX_FORM_ID" dataType="string"/>
<formType fkRef="C1-FRMTY" mapField="FORM_TYPE_CD" dataType="string"/>
<bo suppress="true" required="true" fkRef="F1-BUSOB" mapField="BUS_OBJ_CD" dataType="string"/>
<transferReason mdField="C1_TXF_TFRRSN_FLG" dataType="lookup" mapXML="BO_DATA_AREA" lookup="C1_TXF_TFRRSN_FLG"/>
</schema>'
Select * from [dbo].[udf-XML-Hier](@XML) Order by R1
Returns
您会注意到元素名称、属性名称、XPath、标题(可选)和值列。 R1,R2,Lvl,ID,PT都是派生出来的
作为 TVF,您可以申请任何 WHERE
或 ORDER
所需的
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(10000001 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
*/
获取属性列表的简单方法:
with cte as
(
select cast(
'<schema fwRel="2">
<taxFormId isPrimeKey="true" fkRef="C1-TXFRM" mapField="TAX_FORM_ID" dataType="string" />
<formType fkRef="C1-FRMTY" mapField="FORM_TYPE_CD" dataType="string" />
<bo suppress="true" required="true" fkRef="F1-BUSOB" mapField="BUS_OBJ_CD" dataType="string" />
<transferReason mdField="C1_TXF_TFRRSN_FLG" dataType="lookup" mapXML="BO_DATA_AREA" lookup="C1_TXF_TFRRSN_FLG" />
</schema>' as xml) xml_col
)
--查询使用.nodes(N'/schema/*')
列出<schema>
下方的所有节点,使用.nodes(N'@*')
列出该节点内的所有属性:
select nd.value(N'local-name(.)',N'nvarchar(max)') AS NodeName
,attr.value(N'local-name(.)',N'nvarchar(max)') AS AttrName
,attr.value(N'.',N'nvarchar(max)') AS AttrValue
from cte
OUTER APPLY xml_col.nodes(N'/schema/*') AS A(nd)
OUTER APPLY A.nd.nodes(N'@*') AS B(attr)
结果:
taxFormId isPrimeKey true
taxFormId fkRef C1-TXFRM
taxFormId mapField TAX_FORM_ID
taxFormId dataType string
formType fkRef C1-FRMTY
formType mapField FORM_TYPE_CD
formType dataType string
bo suppress true
bo required true
bo fkRef F1-BUSOB
bo mapField BUS_OBJ_CD
bo dataType string
transferReason mdField C1_TXF_TFRRSN_FLG
transferReason dataType lookup
transferReason mapXML BO_DATA_AREA
transferReason lookup C1_TXF_TFRRSN_FLG
如果您需要像示例中那样的语句,可以动态创建它(作为字符串)并使用 EXEC
执行此语句(动态 SQL).