跳过读取SQL Server存储过程中的XML元素

跳过读取SQL Server存储过程中的XML元素,xml,stored-procedures,sql-server-2016,Xml,Stored Procedures,Sql Server 2016,我在SQL Server 2016中有一个读取XML文件的存储过程。如果没有值,我想做的是跳过保存元素 XML元素应该如下所示 <PROJECT_TERMSX> <TERM>Extramural Activities</TERM> <TERM>programs</TERM> <TERM>research facility</TERM> </PROJECT_TERMSX&g

我在SQL Server 2016中有一个读取XML文件的存储过程。如果没有值,我想做的是跳过保存元素

XML元素应该如下所示

<PROJECT_TERMSX>
      <TERM>Extramural Activities</TERM>
      <TERM>programs</TERM>
      <TERM>research facility</TERM>
</PROJECT_TERMSX>
我想跳过具有http模式但不知道如何构造代码的元素。我无法控制原始XML结构。

您就快到了。XPath表达式
.nodes('/PROJECT\u TERMSX/TERM')
将过滤掉不需要的带有空值的XML

SQL


有时标准化可以帮助您很多,即使需要更多的步骤。在我的例子中,我使用下面的表值函数(见下文)将任何XML文件转换为SQL表,从那里我可以做任何我想做的事情。好的是,我不需要为每个xml更改编写代码,它是动态转换的,我可以将数据作为常规表进行管理

使用:

希望这有帮助

<PROJECT_TERMS xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
INSERT into ADMIN_ExPORTER_TERMS (APPLICATION_ID, TERM)
    SELECT
        APPLICATION_ID,
        nref.value('.','varchar(max)') TERM                     
    FROM 
        [ADMIN_Exporter_Files_XML] 
    CROSS APPLY
        XMLData.nodes('//PROJECT_TERMSX/TERM') AS R(nref)
    WHERE
        APPLICATION_ID = @APPLICATION_ID
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, APPLICATION_ID INT, xmldata XML);
INSERT INTO @tbl (APPLICATION_ID, xmldata)
VALUES (10, N'<PROJECT_TERMSX>
      <TERM>Extramural Activities</TERM>
      <TERM>programs</TERM>
      <TERM>research facility</TERM>
</PROJECT_TERMSX>')
, (10, N'<PROJECT_TERMSX xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />');
-- DDL and sample data population, end

DECLARE @APPLICATION_ID INT = 10;

--INSERT into ADMIN_ExPORTER_TERMS (APPLICATION_ID, TERM)
SELECT APPLICATION_ID
    , col.value('(./text())[1]','VARCHAR(MAX)') AS TERM                     
FROM @tbl AS tbl
    CROSS APPLY tbl.XMLData.nodes('/PROJECT_TERMSX/TERM') AS tab(col)
WHERE APPLICATION_ID = @APPLICATION_ID;
+----------------+-----------------------+
| APPLICATION_ID |         TERM          |
+----------------+-----------------------+
|             10 | Extramural Activities |
|             10 | programs              |
|             10 | research facility     |
+----------------+-----------------------+
select *  from Utility.FlattenXml('<a>1</a><b></b><c>3</c>')
USE [YOUR_DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [Utility].[FlattenXml](@xmlDoc XML)  
RETURNS TABLE 
AS RETURN 
WITH CTE AS ( 

    SELECT 
            1 AS lvl,  
            x.value('local-name(.)','NVARCHAR(MAX)') AS Name,  
            CAST(NULL AS NVARCHAR(MAX)) AS ParentName, 
            CAST(1 AS INT) AS ParentPosition, 
            CAST(N'Element' AS NVARCHAR(20)) AS NodeType,  
            x.value('local-name(.)','NVARCHAR(MAX)') AS FullPath,  
            x.value('local-name(.)','NVARCHAR(MAX)')  
            + N'[' 
            + CAST(ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS NVARCHAR)  
            + N']' AS XPath,  
            ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS Position, 
            x.value('local-name(.)','NVARCHAR(MAX)') AS Tree,  
            x.value('text()[1]','NVARCHAR(MAX)') AS Value,  
            x.query('.') AS this,         
            x.query('*') AS t,  
            CAST(CAST(1 AS VARBINARY(4)) AS VARBINARY(MAX)) AS Sort,  
            CAST(1 AS INT) AS ID  
    FROM @xmlDoc.nodes('/*') a(x)  
    UNION ALL 
    SELECT 
            p.lvl + 1 AS lvl,  
            c.value('local-name(.)','NVARCHAR(MAX)') AS Name,  
            CAST(p.Name AS NVARCHAR(MAX)) AS ParentName, 
            CAST(p.Position AS INT) AS ParentPosition, 
            CAST(N'Element' AS NVARCHAR(20)) AS NodeType,  
            CAST(p.FullPath + N'/' + c.value('local-name(.)','NVARCHAR(MAX)') AS NVARCHAR(MAX)) AS FullPath,  
            CAST(p.XPath + N'/'+ c.value('local-name(.)','NVARCHAR(MAX)')+ N'['+ CAST(ROW_NUMBER() OVER(PARTITION BY c.value('local-name(.)','NVARCHAR(MAX)') 
            ORDER BY (SELECT 1)) AS NVARCHAR)+ N']' AS NVARCHAR(MAX)) AS XPath,  
            ROW_NUMBER() OVER(PARTITION BY c.value('local-name(.)','NVARCHAR(MAX)')
            ORDER BY (SELECT 1)) AS Position, 
            CAST( SPACE(2 * p.lvl - 1) + N'|' + REPLICATE(N'-', 1) + c.value('local-name(.)','NVARCHAR(MAX)') AS NVARCHAR(MAX)) AS Tree,  
            CAST( c.value('text()[1]','NVARCHAR(MAX)') AS NVARCHAR(MAX) ) AS Value, c.query('.') AS this,  
            c.query('*') AS t,  
            CAST(p.Sort + CAST( (lvl + 1) * 1024 + (ROW_NUMBER() OVER(ORDER BY (SELECT 1)) * 2) AS VARBINARY(4)) AS VARBINARY(MAX) ) AS Sort,  
            CAST((lvl + 1) * 1024 + (ROW_NUMBER() OVER(ORDER BY (SELECT 1)) * 2) AS INT)

    FROM CTE p  
    CROSS APPLY p.t.nodes('*') b(c)), cte2 AS (  
                                                SELECT 
                                                lvl AS Depth,  
                                                Name AS NodeName,  
                                                ParentName, 
                                                ParentPosition, 
                                                NodeType,  
                                                FullPath,  
                                                XPath,  
                                                Position, 
                                                Tree AS TreeView,  
                                                Value,  
                                                this AS XMLData,  
                                                Sort, 
                                                ID
                                                FROM cte  
    UNION ALL 
    SELECT 
            p.lvl,  
            x.value('local-name(.)','NVARCHAR(MAX)'),  
            p.Name, 
            p.Position, 
            CAST(N'Attribute' AS NVARCHAR(20)),  
            p.FullPath + N'/@' + x.value('local-name(.)','NVARCHAR(MAX)'),  
            p.XPath + N'/@' + x.value('local-name(.)','NVARCHAR(MAX)'),  
            1, 
            SPACE(2 * p.lvl - 1) + N'|' + REPLICATE('-', 1)  
            + N'@' + x.value('local-name(.)','NVARCHAR(MAX)'),  
            x.value('.','NVARCHAR(MAX)'),  
            NULL,  
            p.Sort,  
            p.ID + 1  
    FROM CTE p  
    CROSS APPLY this.nodes('/*/@*') a(x)  
    )  

    SELECT 
            ROW_NUMBER() OVER(ORDER BY Sort, ID) AS ID,  
            ParentName, ParentPosition,Depth, NodeName, Position,   
            NodeType, FullPath, XPath, TreeView, Value, XMLData 
    FROM CTE2