在SQL Server中的XML列中清空标记格式

时间:2018-02-12 10:09:43

标签: sql-server xml sqlxml

我有这样的xml:

<root>
   <name></name>
</root>

当我保存它时,数据库到XML列并查询例如在SSMS中,它使用自闭标签进行格式化:

<root>
   <name />
</root>

是否可以保留原始格式,或确定SELECT语句中的格式?

2 个答案:

答案 0 :(得分:1)

如果您以非xml格式获取数据,并且不想要自我结束标记,则需要将 NULL 替换为空字符串: ISNULL([YourColumn],'')

例如:

CREATE TABLE #Sample ([name] char(1));
INSERT INTO #Sample
VALUES(NULL);


SELECT ISNULL([Name],'') AS [name]
FROM #Sample
FOR XML PATH('root');

DROP TABLE #Sample;

但是,如果您将xml作为xml类型插入到SQL Server中,然后将其返回,则SQL Server将使用自动关闭标记(根据我对该问题的评论)。

正如@DavidG所说,任何好的 xml解析器都能够读取自闭合和非自闭合标记。如果您的解析器无法读取自闭合标记,则需要考虑更新解析器。如果它纯粹用于显示目的......那你为什么要使用“旧”方式进行显示呢?

答案 1 :(得分:0)

自闭元素<SomeElement/>在语义上与<SomeElement></SomeElement>相同。你不应该为此烦恼...如果你的阅读工具(或第三方要求)需要这个,你应该更换这个工具或与你的伙伴讨论。

问题是:你无法控制,事情保持不变。即使在您能够使用开始和结束标记存储空值的情况下,这可能会在以后调用时隐式更改。

试试这个:

DECLARE @tbl TABLE(ID INT IDENTITY,YourXML XML);
INSERT INTO @tbl VALUES
(
    (SELECT '' AS [SomeTag] FOR XML PATH('RowNode'),ROOT('RootNode'),TYPE)
)
,(
    (SELECT '' AS [SomeTag] FOR XML RAW('RowNode'),ROOT('RootNode'), ELEMENTS)
)
,(
    N'<RootNode>
      <RowNode>
        <SomeTag></SomeTag>
      </RowNode>
    </RootNode>'
)
,
(CAST(
    N'<RootNode>
      <RowNode>
        <SomeTag></SomeTag>
      </RowNode>
    </RootNode>'AS XML)
);

DECLARE @FirstXml XML=(SELECT YourXml FROM @tbl WHERE ID=1);
INSERT INTO @tbl VALUES(@FirstXml);
INSERT INTO @tbl SELECT @FirstXml;
INSERT INTO @tbl SELECT @FirstXml.query(N'.');

SELECT * FROM @tbl

结果

ID  YourXML
--FOR XML PATH created - why ever - both tags
1   <RootNode><RowNode><SomeTag></SomeTag></RowNode></RootNode>
--FOR XML AUTO and all implicit casts use self-closing tags
2   <RootNode><RowNode><SomeTag /></RowNode></RootNode>
3   <RootNode><RowNode><SomeTag /></RowNode></RootNode>
4   <RootNode><RowNode><SomeTag /></RowNode></RootNode>
--Here we insert the first node *as is*
5   <RootNode><RowNode><SomeTag></SomeTag></RowNode></RootNode>
6   <RootNode><RowNode><SomeTag></SomeTag></RowNode></RootNode>
--But `.query()` will reformat this
7   <RootNode><RowNode><SomeTag /></RowNode></RootNode>

一些背景:

XML不会存储为您看到的字符串字符串表示形式,而是存储为层次结构表。每当您获得屏幕上显示的XML时,其字符串表示形式将从头开始重建。每次调用它时都会略有不同(例如属性的顺序,CDATA部分,空元素)。

如果需要,您只能在字符串级别强制执行此格式。您可以使用某种RegEx方法,将<abc/>替换为<abc></abc>

但是又一次:你不应该考虑那个......

更新

使用此SELECT

尝试上述代码
SELECT *
      ,CAST(YourXML AS NVARCHAR(MAX)) AS CastedToString
FROM @tbl

结果

ID  YourXML 
    CastedToString

    --implicitly changed to self-closing tags
1   <RootNode><RowNode><SomeTag></SomeTag></RowNode></RootNode> 
    <RootNode><RowNode><SomeTag/></RowNode></RootNode>

    --Self-closing **without a blank!!!**
2   <RootNode><RowNode><SomeTag /></RowNode></RootNode> 
    <RootNode><RowNode><SomeTag/></RowNode></RootNode>

你可以看到,字符串级别上的比较并不那么容易......而且很难预测......你可以使用CAST(YourXml.query(N'.') AS NVARCHAR(MAX))对每个XML进行相同的操作......