基于XML的文档类型定义的动态表创建

时间:2015-12-14 14:14:49

标签: c# sql xml tsql powershell

早安技师,

愿任何人分享你的专长。

我有一个带有文档类型定义的XML文档(1GB大小)。

我需要将数据加载到sql表,但挑战是必须在运行时创建的表结构取决于.dtd文件。

.dtd文件会根据客户与客户的不断变化

我是xml的新手,请帮帮我。如果需要,我可以提供xml和.dtd。

代码我习惯将数据从xml提取到表格

;With Cte

 AS

 (SELECT i.value('(../@action)[1]','varchar(20)') AppAction,

        i.value('(../@id)[1]','varchar(20)') AppId,

      i.value('.','varchar(20)') Notes,

     i.value('(../BaseVehicle/@id)[1]','varchar(20)') BaseVehicle,

      k.value('(./Qual/@id)[1]','varchar(20)') Qual,

     i.value('(../Qty)[1]','varchar(20)') Qty,

    i.value('(../PartType/@id)[1]','varchar(20)') PartType,

   i.value('(../SubModel/@id)[1]','varchar(20)') SubModel,
    i.value('(../EngineBase/@id)[1]','varchar(20)') EngineBase,
    i.value('(../EngineVIN/@id)[1]','varchar(20)') EngineVIN,
    k.value('(./MfrLabel)[1]','varchar(20)') MfrLabel,
    i.value('(../Position/@id)[1]','varchar(20)') PositionId,
    i.value('(../Part)[1]','varchar(20)') Part,
    k.value('(./Qual/param/@value)[1]','varchar(20)') ParamValue,
    j.value('.','varchar(20)') RecordCount

FROM @X.nodes('AMUL/App[@action="A"]/Note') x(i)

OUTER APPLY x.i.nodes('../../Footer/RecordCount')y(j) 

OUTER APPLY y.j.nodes('../../App')z(k))

 SELECT 


AppAction,AppId,BaseVehicle,Qual,Qty,PartType,MfrLabel,PositionId,Part,ParamValue,SubModel,EngineBase,EngineVIN,RecordCount,

       STUFF((SELECT ' ; ' + Notes 

            FROM   Cte X WHERE X.BaseVehicle = Y.BaseVehicle 

           GROUP  BY BaseVehicle,Notes

          FOR XML PATH('')), 1, 2, '') Note                 

FROM   Cte Y 

 GROUP  BY 
BaseVehicle,AppAction,AppId,Qual,Qty,PartType,MfrLabel,PositionId,Part,ParamValue,SubModel,EngineBase,EngineVIN,RecordCount

非常感谢。

1 个答案:

答案 0 :(得分:2)

这是第一次尝试:

它将创建(实际上只是声明)四个表(文件,app,qual和note) 您的数据将使用创建的外键插入。 最后一行是完全连接的结果集 我将所有XML节点都包含在目标表中,以确保丢失的信息不会丢失......

只需将整个事物复制到一个空的查询窗口中,执行并探索最终结果是否符合您的需求。

如果是,请不要忘记投票并接受。这需要付出相当大的努力: - )

快乐的编码!

DECLARE @x xml='<?xml version="1.0" encoding="utf-8"?> 
<ACES version="3.0"> 
<Header> 
<Company>Godrej</Company> 
<SenderName>chail</SenderName> 
<SenderPhone>xxx-712-xxxx</SenderPhone> 
<TransferDate>2009-09-30</TransferDate> 
<BrandAAIAID>tbzx</BrandAAIAID> 
<DocumentTitle>Godrej Data</DocumentTitle> 
<EffectiveDate>2009-09-30</EffectiveDate> 
<SubmissionType>FULL</SubmissionType> 
<xcdbVersionDate>2008-08-28</xcdbVersionDate> 
<reltersionDate>2008-06-10</reltersionDate> 
<xcbdVersionDate>2020-09-25</xcbdVersionDate> 
</Header> 

<App action="A" id="1"> 
<BaseVehicle id="2555"/> 
<Qual id="15231"> 
<text>Light Duty Brakes</text> 
</Qual> 
<Qty>2</Qty> 
<PartType id="10054"/> 
<MfrLabel>Professional Grade</MfrLabel> 
<Position id="22"/> 
<Part>816-4000</Part> 
</App> 
<App action="A" id="3"> 
<BaseVehicle id="2557"/> 
<Qual id="15231"> 
<text>Light Duty Brakes</text> 
</Qual> 
<Qty>2</Qty> 
<PartType id="10054"/> 
<MfrLabel>Professional Grade</MfrLabel> 
<Position id="22"/> 
<Part>816-4000</Part> 
</App> 
<App action="A" id="908"> 
<BaseVehicle id="1513"/> 
<Qual id="9174"> 
<text>Standard Nut</text> 
</Qual> 
<Qual id="21521"> 
<text>Requires Stamped Retainer And Cotter Pin</text> 
</Qual> 
<Qty>2</Qty> 
<PartType id="10054"/> 
<MfrLabel>Professional Grade</MfrLabel> 
<Position id="22"/> 
<Part>816-4018</Part> 
</App> 
<App action="A" id="4007"> 
<BaseVehicle id="7947"/> 
<Qual id="9743"> 
<param value="8/91"/> 
<text>Thru 8/91</text> 
</Qual> 
<Qty>2</Qty> 
<PartType id="10014"/> 
<MfrLabel>Professional Grade</MfrLabel> 
<Position id="22"/> 
<Part>816-4265</Part> 
</App> 
<App action="A" id="1"> 
<BaseVehicle id="5861" /> 
<Note>Manual</Note> 
<Qty>1</Qty> 
<PartType id="13117" /> 
<Position id="12" /> 
<Part>955-304</Part> 
</App> 

<App action="A" id="9951"> 
<BaseVehicle id="3883" /> 
<Note>Reflector</Note> 
<Note>Packaging Type: Box</Note> 
<Qty>1</Qty> 
<PartType id="11720" /> 
<Position id="88" /> 
<Part>1650140</Part> 
</App> 
<App action="A" id="16578"> 
<BaseVehicle id="18667" /> 
<SubModel id="694" /> 
<Note>Composite Type</Note> 
<Note>Smoked Lens, w/Black Trim</Note> 
<Qty>1</Qty> 
<PartType id="10762" /> 
<Position id="12" /> 
<Part>1591142</Part> 
</App> 
<App action="A" id="19633"> 
<BaseVehicle id="18659" /> 
<Note>Power</Note> 
<Note>w/Heat</Note> 
<Note>wo/Memory</Note> 
<Qty>1</Qty> 
<PartType id="13117" /> 
<Position id="12" /> 
<Part>955-1162</Part> 
</App> 
<App action="A" id="83948"> 
<BaseVehicle id="4470" /> 
<Note>Compare to Original</Note> 
<Note>Bulb Call-Out Size: 194</Note> 
<Note>Wattage: 1.2</Note> 
<Note>Light Color: White</Note> 
<Qty>1</Qty> 
<PartType id="11730" /> 
<Position id="1" /> 
<Part>194W-SMD</Part> 
</App> 
<App action="A" id="2"> 
<BaseVehicle id="4935" /> 
<Note>M14 x 1.50 Thread</Note> 
<Note>Package Quantity: 5</Note> 
<Note>Dorman - AutoGrade - Boxed</Note> 
<Note>Packaging Type: Box</Note> 
<Qty>1</Qty> 
<PartType id="5560" /> 
<Position id="1" /> 
<Part>090-053</Part> 
</App> 
<App action="A" id="288250"> 
<BaseVehicle id="16865" /> 
<SubModel id="20" /> 
<EngineBase id="5461" /> 
<EngineVIN id="40" /> 
<Note>Wheel Lock Type: Female Spline</Note> 
<Note>Package Quantity: 4</Note> 
<Note>Packaging Type: Card</Note> 
<Note>Thread Size: 1/2-20</Note> 
<Note>Chrome</Note> 
<Note>Overall Length (In): 1.425</Note> 
<Note>Steel</Note> 
<Note>Thread Handling: Right Hand Thread</Note> 
<Qty>1</Qty> 
<PartType id="16214" /> 
<Position id="1" /> 
<Part>711-221</Part> 
</App> 
<Footer> 
<RecordCount>1772522</RecordCount> 
</Footer> 
</ACES>';


DECLARE @tblFile TABLE(FileID INT
                  ,ACES_Version VARCHAR(10)
                  ,Header_Company VARCHAR(100)
                  ,Header_SenderName VARCHAR(100)
                  --further Header-fields here 
                  ,Footer_RecordCount INT
                  ,HeaderNode XML
                  ,FooterNode XML);

INSERT INTO @tblFile
SELECT 1 AS FileID --Add something senseful here
      ,@x.value('/ACES[1]/@version','varchar(max)') AS ACES_Version
      ,@x.value('(/ACES/Header/Company)[1]','varchar(max)') AS Header_Company
      ,@x.value('(/ACES/Header/SenderName)[1]','varchar(max)') AS Header_SenderName
      --further fields of header here
      ,@x.value('(/ACES/Footer/RecordCount)[1]','int') AS ACES_RecordCount
      ,@x.query('/ACES/Header') AS HeaderNode
      ,@x.query('/ACES/Footer') AS FooterNode;

DECLARE @tblApp TABLE(AppID INT
                     ,FileID INT
                     ,Action VARCHAR(10)
                     ,ID INT
                     ,BaseVehicleID INT
                     ,Qty INT
                     --further App-fields here
                     ,QualNodes XML
                     ,NoteNodes XML
                     ,AppNode XML);

INSERT INTO @tblApp
SELECT ROW_NUMBER() OVER(ORDER BY One.App.value('@id','int')) AS AppID
      ,1 AS FileID --Add something senseful here
      ,One.App.value('@action','varchar(10)') AS Action
      ,One.App.value('@id','int') AS ID
      ,One.App.value('BaseVehicle[1]/@id','int') AS BaseVehicleID
      ,One.App.value('Qty[1]','int') AS Qty
      --further App-fields here
      ,'<Quals>' + CAST(One.App.query('Qual') AS VARCHAR(MAX)) + '</Quals>' AS QualNodes
      ,'<Notes>' + CAST(One.App.query('Note') AS VARCHAR(MAX)) + '</Notes>' AS NoteNodes
      ,One.App.query('.') AS AppNode
FROM @x.nodes('/ACES/App') AS One(App);

DECLARE @tblQual TABLE(AppID INT
                      ,FileID INT
                      ,QualID INT
                      ,ID INT
                      ,Text VARCHAR(150)
                      ,ParamValue VARCHAR(150)
                      ,QualNode XML);

INSERT INTO @tblQual
SELECT AppID
      ,FileID
      ,ROW_NUMBER() OVER(PARTITION BY AppID ORDER BY One.Qual.value('@id','int')) AS QualID
      ,One.Qual.value('@id','int') AS ID
      ,One.Qual.value('text[1]','varchar(max)') AS Text
      ,One.Qual.value('param[1]/@value','varchar(max)') AS ParamValue
      ,One.Qual.query('.') AS QualNode
FROM @tblApp AS tblApp
CROSS APPLY tblApp.QualNodes.nodes('/Quals/Qual') One(Qual)


DECLARE @tblNotes TABLE(AppID INT
                      ,FileID INT
                      ,NoteID INT
                      ,ID INT
                      ,NoteText VARCHAR(150)
                      ,NoteNode XML);

INSERT INTO @tblNotes
SELECT AppID
      ,FileID  
      ,ROW_NUMBER() OVER(PARTITION BY AppID ORDER BY (SELECT NULL)) AS NoteID
      ,One.Note.value('@id','int') AS ID
      ,One.Note.value('.','varchar(max)') AS NoteText
      ,One.Note.query('.') AS NoteNode
FROM @tblApp AS tblApp
CROSS APPLY tblApp.NoteNodes.nodes('/Notes/Note') One(Note)

SELECT * 
FROM @tblFile AS f
INNER JOIN @tblApp AS a ON f.FileID=a.FileID
LEFT JOIN @tblQual AS q ON q.AppID=a.AppID
LEFT JOIN @tblNotes AS n ON n.AppID=a.AppID