Home > database >  XML Document to SQL Server Query
XML Document to SQL Server Query

Time:10-14

How to get data from XML file to SQL query, following code is not working.

<FVDL>
        <EngineData>
           <RuleInfo>
             <Rule id="13EFF385-69A9-494A-9C67-951FEDAB25ED">
               <MetaInfo>
                 <Group name="package">Python Core xml</Group>
                 <Group name="inputsource">XML Document</Group>
                 <Group name="audience">broad</Group>
               </MetaInfo>
             </Rule>
            <Rule id="E9DB1C0E-025E-4EBF-A804-6C3DA413E652">
               <MetaInfo>
                 <Group name="altcategoryMIS">Python Core zipfile</Group>
                 <Group name="altcategoryGDPR">Access Violation</Group>
               </MetaInfo>
             </Rule>  
           </RuleInfo>
        </EngineData>
    </FVDL>
             
    
    USE OPENXMLTesting
    GO
    
    DECLARE @XML AS XML, @hDoc AS INT
    
    SELECT @XML = XMLData FROM XMLwithOpenXML
    
    EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
    
    Select ID, name, [Group]
    FROM OPENXML(@hDoc, 'FVDL/EngineData/RuleInfo') 
    
    WITH  
    (
    ID [varchar](100) 'Rule/@id',
    [name] [varchar](100) 'Rule/MetaInfo/Group/@name',
    [Group] [varchar](1000) 'MetaInfo/Group/.. '
    )  
    
    EXEC sp_xml_removedocument @hDoc

Looking for result like this

ID Name Group
13EFF385-69A9-494A-9C67-951FEDAB25ED package Python Core xml
13EFF385-69A9-494A-9C67-951FEDAB25ED nputsource XML Document
13EFF385-69A9-494A-9C67-951FEDAB25ED audience broad
E9DB1C0E-025E-4EBF-A804-6C3DA413E652 altcategoryMIS Python Core zipfile
E9DB1C0E-025E-4EBF-A804-6C3DA413E652 altcategoryGDPR Access Violation

CodePudding user response:

Please try the following solution.

Starting from SQL Server 2005 onwards, it is better to use XQuery language, based on the w3c standards, while dealing with the XML data type.

Microsoft proprietary OPENXML and its companions sp_xml_preparedocument and sp_xml_removedocument are kept just for backward compatibility with the obsolete SQL Server 2000. Their use is diminished just to very few fringe cases. It is strongly recommended to re-write your SQL and switch it to XQuery.

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata) VALUES
(N'<FVDL>
    <EngineData>
        <RuleInfo>
            <Rule id="13EFF385-69A9-494A-9C67-951FEDAB25ED">
                <MetaInfo>
                    <Group name="package">Python Core xml</Group>
                    <Group name="inputsource">XML Document</Group>
                    <Group name="audience">broad</Group>
                </MetaInfo>
            </Rule>
            <Rule id="E9DB1C0E-025E-4EBF-A804-6C3DA413E652">
                <MetaInfo>
                    <Group name="altcategoryMIS">Python Core zipfile</Group>
                    <Group name="altcategoryGDPR">Access Violation</Group>
                </MetaInfo>
            </Rule>
        </RuleInfo>
    </EngineData>
</FVDL>');
-- DDL and sample data population, end

SELECT p.value('@id', 'UNIQUEIDENTIFIER') AS ID
    , c.value('@name', 'VARCHAR(30)')AS [Name]
    , c.value('(./text())[1]', 'VARCHAR(30)')AS [Group]
FROM @tbl
    CROSS APPLY xmldata.nodes('/FVDL/EngineData/RuleInfo/Rule') AS t1(p)
    CROSS APPLY t1.p.nodes('MetaInfo/Group') AS t2(c);

Output

 -------------------------------- ----------------- --------------------- 
|               ID               |      Name       |       Group         |
 -------------------------------- ----------------- --------------------- 
| 13EFF385-69A9-494A-9C67-951FED | package         | Python Core xml     |
| 13EFF385-69A9-494A-9C67-951FED | inputsource     | XML Document        |
| 13EFF385-69A9-494A-9C67-951FED | audience        | broad               |
| E9DB1C0E-025E-4EBF-A804-6C3DA4 | altcategoryMIS  | Python Core zipfile |
| E9DB1C0E-025E-4EBF-A804-6C3DA4 | altcategoryGDPR | Access Violation    |
 -------------------------------- ----------------- --------------------- 

CodePudding user response:

OPENXML is a bit wonky and is outdated. If you need to use it, you need to provide the path down to <Group> and then work your way back up to the other elements. This should do it for you based on your sample XML.

DECLARE @XML XML = N'<FVDL>
        <EngineData>
           <RuleInfo>
             <Rule id="13EFF385-69A9-494A-9C67-951FEDAB25ED">
               <MetaInfo>
                 <Group name="package">Python Core xml</Group>
                 <Group name="inputsource">XML Document</Group>
                 <Group name="audience">broad</Group>
               </MetaInfo>
             </Rule>
            <Rule id="E9DB1C0E-025E-4EBF-A804-6C3DA413E652">
               <MetaInfo>
                 <Group name="altcategoryMIS">Python Core zipfile</Group>
                 <Group name="altcategoryGDPR">Access Violation</Group>
               </MetaInfo>
             </Rule>  
           </RuleInfo>
        </EngineData>
    </FVDL>'
    
DECLARE @hDoc AS INT
    
EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
    
Select ID, name, [Group]
FROM OPENXML(@hDoc, 'FVDL/EngineData/RuleInfo/Rule/MetaInfo/Group') 
WITH  
(
    id [varchar](100) '../../@id',
    [name] [varchar](100) '@name',
    [Group] [varchar](1000) '.'
)  
    
EXEC sp_xml_removedocument @hDoc

CodePudding user response:

I strongly suggest you don't use OPENXML, as it has many issues.

Instead use the newer XQuery functions, which are far simpler to use

  • Note how one .nodes feeds into the next. This is only necessary because there are two separate levels of nodes that need breaking into separate rows.
SELECT
    ID = rl.value('@id','uniqueidentifier'),
    [name] = grp.value('@name', 'varchar(100)'),
    [Group] = grp.value('text()[1]','varchar(1000)')
FROM XMLwithOpenXML
CROSS APPLY XMLData.nodes('FVDL/EngineData/RuleInfo/Rule') x1(rl)
CROSS APPLY x1.rl.nodes('MetaInfo/Group') x2(Grp);

db<>fiddle

  • Related