我有这样的xml:
<root>
<name></name>
</root>
当我保存它时,数据库到XML列并查询例如在SSMS中,它使用自闭标签进行格式化:
<root>
<name />
</root>
是否可以保留原始格式,或确定SELECT语句中的格式?
答案 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进行相同的操作......