Open XML document and return for every row, based on row's path to xml file

前端 未结 2 446
难免孤独
难免孤独 2020-12-12 03:30

I\'m pretty new to using XML with TSQL, and recently ran into an issue that I can\'t think around and need your help with.

Scenario: I have a query

2条回答
  •  难免孤独
    2020-12-12 04:22

    Your question is two folded:

    • read the files with dynamically set file paths
    • Find a query to read from the XMLs

    Part 1: Read the files

    Try this:

    DECLARE @mockup TABLE([GUID] VARCHAR(100),filePath VARCHAR(100));
    INSERT INTO @mockup VALUES
     ('0001','\\YourPath\File1.xml')
    ,('0002','\\YourPath\File2.xml')
    ,('0003','\\YourPath\File3.xml');
    

    --Use a physically created table as staging table

    CREATE TABLE StagingFileContent([GUID] VARCHAR(100),FileContent VARBINARY(MAX));
    

    --A cursor-loop will read the file names and call OPENROWSET with dynamic SQL

    DECLARE @g VARCHAR(100),@fp VARCHAR(100);
    DECLARE @cmd VARCHAR(MAX);
    
    DECLARE cur CURSOR FOR SELECT [GUID],filePath FROM @mockup;
    OPEN cur;
    FETCH NEXT FROM cur INTO @g,@fp;
    WHILE @@FETCH_STATUS=0
    BEGIN
        SET @cmd='INSERT INTO StagingFileContent([GUID],FileContent) ' +
                 'SELECT ''' + @g + ''',* FROM OPENROWSET(BULK ''' +  @fp + ''', SINGLE_BLOB) AS Contents;'
        EXEC(@cmd);
    FETCH NEXT FROM cur INTO @g,@fp;
    END 
    CLOSE cur;
    DEALLOCATE cur;
    

    --Now the staging table holds the GUID and the content as VARBINARY(MAX)

    SELECT * FROM StagingFileContent;
    

    Hint:

    This might be depending on the encoding of your files. You can try SINGLE_CLOB and using VARCHAR(MAX) or NVARCHAR(MAX) instead of VARBINARY(MAX)

    Part 2: Read the XMLs

    Try this, the table is simulating your staging table:

    DECLARE @xmls TABLE([GUID] VARCHAR(100),FileContent VARBINARY(MAX));
    INSERT INTO @xmls VALUES
    ('0001',CAST(N'
    TextboxAllocation3 0 TextboxAllocation1 0 TextboxAllocation2 0
    ' AS VARBINARY(MAX))) ,('0002',CAST(N'
    SomeMore 1 EvenMore 2
    ' AS VARBINARY(MAX))); WITH Casted AS ( SELECT [GUID],CAST(CAST(FileContent AS NVARCHAR(MAX)) AS XML) AS YourXML FROM @xmls ) SELECT [GUID] ,f.value(N'(name/text())[1]','nvarchar(max)') AS FieldName ,f.value(N'(value/text())[1]','nvarchar(max)') AS FieldValue FROM Casted CROSS APPLY YourXML.nodes(N'/form/field') AS A(f);

    The result:

    GUID    FieldName          FieldValue
    0001    TextboxAllocation3  0
    0001    TextboxAllocation1  0
    0001    TextboxAllocation2  0
    0002    SomeMore            1
    0002    EvenMore            2
    

提交回复
热议问题