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

前端 未结 2 431
难免孤独
难免孤独 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:09

    You can query the xml as below: Not sure what you are trying to do with GUID.. If you have that column in different table you can do cross apply to below query and get xml's output:

    declare @x xml = '<form>
      <field>
        <name>TextboxAllocation3</name>
        <value>0</value>
      </field>
      <field>
        <name>TextboxAllocation1</name>
        <value>0</value>
      </field>
      <field>
        <name>TextboxAllocation2</name>
        <value>0</value>
      </field>
    </form>'
    
    Select  T.c.value('name[1]', 'varchar(20)') as [Name],
            T.c.value('value[1]','int') as [Value]
    from @x.nodes('form/field') T(c)
    
    0 讨论(0)
  • 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'<form>
                  <field>
                    <name>TextboxAllocation3</name>
                    <value>0</value>
                  </field>
                  <field>
                    <name>TextboxAllocation1</name>
                    <value>0</value>
                  </field>
                  <field>
                    <name>TextboxAllocation2</name>
                    <value>0</value>
                  </field>
                </form>' AS VARBINARY(MAX)))
    ,('0002',CAST(N'<form>
                  <field>
                    <name>SomeMore</name>
                    <value>1</value>
                  </field>
                  <field>
                    <name>EvenMore</name>
                    <value>2</value>
                  </field>
                </form>' 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
    
    0 讨论(0)
提交回复
热议问题