2012-11-20 30 views
2

我使用FOR XML PATH从SQL Server 2008R2中的表中构建XML。该XML具有如下构成:使用T-SQL FOR XML路径删除空的XML节点

<Root> 
    <OuterElement> 
     <NumberNode>1</NumberNode> 
     <FormattedNumberNode>0001</KFormattedNumberNode> 
     <InnerContainerElement> 
      <InnerNodeOne>0240</InnerNodeOne> 
      <InnerNodeStartDate>201201</InnerNodeStartDate> 
     </InnerContainerElement> 
    </OuterElement> 
</Root> 

根据架构文件,该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] 

我能想到的两种方法构造此XML与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 

2)用 'InnerContainerElement' 作为从XML子查询的输出元件,但没有将其命名为:

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

然而,他们没有给出期望的结果:在这两种情况下,结果看起来像

<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> 

只要InnerContainerElement为空,它仍然显示为空元素。根据模式,这是无效的:只要元素InnerContainerElement在XML中,则也需要InnerNodeOne

我该如何构建我的FOR XML PATH查询,以便InnerContainerElement在空的时候被省略掉?

回答

4

您需要确保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') 

或者你可以为列别名的一部分指定元素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')