2012-11-20 79 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')