繁体   English   中英

用于提取元素 XML 属性的循环

[英]Loop for extracting attributes of elements XML

我需要从一长串各种元素中提取所有属性。 因此,我正在寻求构建一个循环遍历我的所有元素并返回它们的属性。

通过几篇文章,我已经能够编写下面的代码。 但是,我有超过 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

我希望我提供了足够的信息

列出属性的简单方法:

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 )。

这可能有点过头了,但我经常使用 TVF 来解析和散列大型 XML 文件。 该函数将返回具有范围键 R1/R2 的父/子层次结构中的数据。

例如:

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

退货

在此处输入图片说明

您会注意到有元素名称、属性名称、XPath、标题(可选)和值的列。 R1、R2、Lvl、ID 和 PT 都是派生的。

作为 TVF,您可以申请任何所需的WHEREORDER


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
*/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM