使用 T-SQL FOR XML PATH 删除空的 XML 节点

vst*_*ien 4 xml t-sql sql-server for-xml-path

我正在使用FOR XML PATHSQL Server 2008R2 中的表构造 XML。XML 必须构造如下:

<Root>
    <OuterElement>
        <NumberNode>1</NumberNode>
        <FormattedNumberNode>0001</KFormattedNumberNode>
        <InnerContainerElement>
            <InnerNodeOne>0240</InnerNodeOne>
            <InnerNodeStartDate>201201</InnerNodeStartDate>
        </InnerContainerElement>
    </OuterElement>
</Root>
Run Code Online (Sandbox Code Playgroud)

根据模式文件,InnerContainerElement是可选的,而InnerNodeOne是必需的。架构文件不是由我设置的,非常复杂,相互引用并且没有明确的 XSD 命名空间,因此我无法轻松将它们加载到数据库中。

XML 必须从一个表中创建,该表使用以下查询填充:

SELECT
    1 AS NumberNode
    , '0001' AS [FormattedNumberNode]
    , '0240' AS [InnerNodeOne]
    , '201201' AS [InnerNodeStartDate]
INTO #temporaryXMLStore
UNION
SELECT
    2 AS NumberNode
    , '0001' AS [FormattedNumberNode]
    , NULL AS [InnerNodeOne]
    , NULL AS [InnerNodeStartDate]
Run Code Online (Sandbox Code Playgroud)

我可以想到两种使用FOR XML PATH.

1) 使用 'InnerContainerElement' 作为来自 XML 子查询的命名结果:

SELECT
    NumberNode
    , [FormattedNumberNode]
    , (
        SELECT
            [InnerNodeOne]
            , [InnerNodeStartDate]
        FOR XML PATH(''), TYPE
    ) AS [InnerContainerElement]
FROM #temporaryXMLStore
FOR XML PATH('OuterElement'), ROOT('Root') TYPE
Run Code Online (Sandbox Code Playgroud)

2) 使用“InnerContainerElement”作为来自 XML 子查询的输出元素,但没有命名:

SELECT
    NumberNode
    , [FormattedNumberNode]
    , (
        SELECT
            [InnerNodeOne]
            , [InnerNodeStartDate]
        FOR XML PATH('InnerContainerElement'), TYPE
    )
FROM #temporaryXMLStore
FOR XML PATH('OuterElement'), ROOT('Root'), TYPE
Run Code Online (Sandbox Code Playgroud)

然而,它们都没有给出想要的结果:在这两种情况下,结果看起来都像

<Root>
  <OuterElement>
    <NumberNode>1</NumberNode>
    <FormattedNumberNode>0001</FormattedNumberNode>
    <InnerContainerElement>
      <InnerNodeOne>0240</InnerNodeOne>
      <InnerNodeStartDate>201201</InnerNodeStartDate>
    </InnerContainerElement>
  </OuterElement>
  <OuterElement>
    <NumberNode>2</NumberNode>
    <FormattedNumberNode>0001</FormattedNumberNode>
    <InnerContainerElement></InnerContainerElement>
    <!-- Or, when using the second codeblock: <InnerContainerElement /> -->
  </OuterElement>
</Root>
Run Code Online (Sandbox Code Playgroud)

每当InnerContainerElement为空时,它仍然显示为空元素。根据架构,这是无效的:只要元素InnerContainerElement在 XML 中,它InnerNodeOne也是必需的。

我如何构造我的FOR XML PATH查询,以便InnerContainerElement在它为空时被忽略?

Mik*_*son 6

您需要确保在InnerContainerElement没有内容的情况下具有零行。

select T.NumberNode,
       T.FormattedNumberNode,
       (
         select T.InnerNodeOne,
                T.InnerNodeStartDate
         where T.InnerNodeOne is not null or
               T.InnerNodeStartDate is not null
         for xml path('InnerContainerElement'), type
       )
from #temporaryXMLStore as T
for xml path('OuterElement'), root('Root')
Run Code Online (Sandbox Code Playgroud)

或者您可以将元素指定InnerContainerElement为列别名的一部分。

select T.NumberNode,
       T.FormattedNumberNode,
       T.InnerNodeOne as 'InnerContainerElement/InnerNodeOne',
       T.InnerNodeStartDate as 'InnerContainerElement/InnerNodeStartDate'
from #temporaryXMLStore as T
for xml path('OuterElement'), root('Root')
Run Code Online (Sandbox Code Playgroud)