【问题标题】:Unable to generate FOR XML无法生成 FOR XML
【发布时间】:2016-08-10 20:02:43
【问题描述】:

我被FOR XML 卡住了。我正在使用 SQL Server 2008。

我正在尝试使用 FOR XML 生成 XML。 样本数据请见http://sqlfiddle.com/#!9/4e180e

我想将数据转换为以下XML 格式。我想将标签转换为标签<Headers> 并将数据转换为数据标签。在我的实际场景中,表中的列数是动态的。

我希望您能建议一种动态的方式来生成 XML,其中列数不应影响 XML 生成的逻辑。

<RootNode>
    <Subject>
        </SubjectID=94>
        <FORMName>
            <Headers>
                <Header>VISIT</Header>
            </Headers>
            <Datas>
                <Data>1<Data>
            </Datas> 
            <Headers>
                <Header>Date</Header>
            </Headers>
            <Datas>
                <Data>8 Aug<Data>
            </Datas>
            <Headers>
                <Header>Doc Name</Header><Header>Hostipal Name</Header>
            </Headers>
            <Datas>
                <Data>Dr Sam</Data><Data>Happy Memorial</Data>
            </Datas>
            <Datas>
                <Data>Dr Sam</Data><Data>Happy Memorial</Data>
            </Datas>
        </FORMName>
    </Subject>
<RootNode>

我被困在非常初始的水平,无法前进。

请帮助我。

【问题讨论】:

  • @L'Algérino 感谢您的编辑。

标签: xml sql-server-2008 for-xml-path for-xml


【解决方案1】:

这个结构 - 嗯 - 很奇怪......

您的表格类似于Key-Value-Pair,带有1:n-dependency 的标题和数据。这违反了几个规范化规则......

您的 XML 只能通过 Header 及其数据的相应位置进行查询。想象一下一些数据为NULL,你也必须处理这个......

顺便说一句:您的 &lt;/SubjectID=94&gt; 无效...

如果你是这个结构的所有者,你应该考虑我该如何改进这个结构?

尽管如此,这是可以做到的——虽然我不会:

CREATE TABLE DataCols (
ID INT NOT NULL IDENTITY PRIMARY KEY, 
SubjectID INT, 
FormName VARCHAR(100),
ItemDetail VARCHAR(100),
POSITION INT,
col1 VARCHAR(255),
col2 VARCHAR(255)
);

INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1)      VALUES(94,'TOX','Label',0,'Visit');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1)      VALUES(94,'TOX','Data',0,'1');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1)      VALUES(94,'TOX','Label',0,'Date');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1)      VALUES(94,'TOX','Date',0,'8 Aug');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(94,'TOX','Label',1,'Doc Name','Hostipal Name');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(94,'TOX','Data',1,'Dr Sam','Happy Memorial');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(94,'TOX','Data',2,'Dr Sam','Happy Memorial');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1)      VALUES(98,'TOX','Label',0,'Visit');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1)      VALUES(98,'TOX','Data',0,'1');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1)      VALUES(98,'TOX','Label',0,'Date');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1)      VALUES(98,'TOX','Date',0,'4 Jan');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(98,'TOX','Label',1,'Doc Name','Hostipal Name');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(98,'TOX','Data',1,'Dr Sam','Vegas Hostipal');
INSERT INTO DataCols (SubjectID,FormName,ItemDetail,POSITION,col1,col2) VALUES(98,'TOX','Data',2,'Dr Sam','Vegas Hostipal');
GO

--这是查询:

WITH DistinctID AS
(SELECT DISTINCT SubjectID FROM DataCols)
,Labels AS
(
    SELECT SubjectID
          ,ID
          ,(SELECT col1 AS Header,'',col2 AS Header FOR XML PATH('Headers'),TYPE) AS HeaderXML
    FROM DataCols AS c
    WHERE ItemDetail='Label'
)
,LabelsExt AS
(
    SELECT * 
          ,(SELECT MIN(x.ID) FROM Labels AS x WHERE x.ID>Labels.ID) AS NextID
    FROM Labels
)
SELECT SubjectID
      ,(
        SELECT HeaderXML AS [*]
              ,(SELECT col1 AS Data,'',col2 AS Data 
                FROM DataCols 
                WHERE DataCols.ID BETWEEN l.ID+1 AND ISNULL(l.NextID,999999)-1 FOR XML PATH('Datas'),TYPE)  AS [*]
        FROM LabelsExt AS l
        WHERE l.SubjectID=DistinctID.SubjectID
        FOR XML PATH(''),ROOT('FORMName'),TYPE
       )
FROM DistinctID
FOR XML PATH('Subject'),ROOT('RootNode')

--清理(如果是真实数据,请小心!)

GO
--DROP TABLE DataCols;

更新

您可以尝试将标题作为属性添加到您的数据元素中。一般来说,我更愿意将元素命名为它们是什么......这种结构只是在您事先不知道结构的动态创建字段的情况下更喜欢。

WITH DistinctID AS
(SELECT DISTINCT SubjectID FROM DataCols)
,Labels AS
(
    SELECT SubjectID
          ,ID
          ,col1,col2
    FROM DataCols AS c
    WHERE ItemDetail='Label'
)
,LabelsExt AS
(
    SELECT * 
          ,(SELECT MIN(x.ID) FROM Labels AS x WHERE x.ID>Labels.ID) AS NextID
    FROM Labels
)
SELECT SubjectID
      ,(
        SELECT (SELECT l.col1 AS [Data/@header], c.col1 AS Data
                      ,''
                      ,l.col2 AS [Data/@header], c.col2 AS Data 
                FROM DataCols AS c 
                WHERE c.ID BETWEEN l.ID+1 AND ISNULL(l.NextID,999999)-1 
                FOR XML PATH('Datas'),TYPE)  AS [*]
        FROM LabelsExt AS l
        WHERE l.SubjectID=DistinctID.SubjectID
        FOR XML PATH(''),ROOT('FORMName'),TYPE
       )
FROM DistinctID
FOR XML PATH('Subject'),ROOT('RootNode')

【讨论】:

  • 非常感谢您的回复。我来检查一下。是的,我是这个 XML 的所有者,我会尝试采纳您的建议。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-23
  • 1970-01-01
  • 2023-03-11
  • 2012-05-23
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
相关资源
最近更新 更多