我有这样的xml:
<tt>
<cpost/>
<cpost/>
<gx2tov />
<kodp/>
<Sertif1/>
<Sertif1/>
<slmat/>
</tt>
但我需要将其更改为:
<tt>
<slmat/>
<cpost/>
<cpost/>
<kodp/>
<gx2tov />
<Sertif1/>
<Sertif1/>
</tt>
如何使用T SQL做到这一点?
答案 0 :(得分:1)
已经有一个已接受的答案,但它只适用于空节点。在这种情况下,您可以根据需要输入XML ...
更多方法:
我添加了一些id属性来区分相同的元素
DECLARE @xml XML=
'<tt>
<cpost id="1"/>
<cpost id="2"/>
<gx2tov/>
<kodp/>
<Sertif1 id="1"/>
<Sertif1 id="2"/>
<slmat/>
</tt>';
<slmat>
放在顶部您可以使用.query()
获取完整节点,您可以在AS [node()]
中使用SELECT ... FOR XML PATH()
。此查询会将<slmat>
放在顶部,并将所有名称放在后面(原始订单):
SELECT @xml.query(N'/tt/slmat') AS [node()]
,@xml.query(N'/tt/*[local-name()!="slmat"]') AS [node()]
FOR XML PATH(N'tt');
与上述相同,但是只有一个XQuery
SELECT @xml.query
('
<tt>
{tt/slmat}
{tt/*[local-name()!="slmat"]}
</tt>
');
如果您想为元素设置特定订单,可以明确地放置它们(现在我使用.nodes()
,但您也可以不用 - 如上所述):
SELECT tt.query(N'slmat') AS [node()]
,tt.query(N'cpost') AS [node()]
,tt.query(N'kodp') AS [node()]
,tt.query(N'gx2tov') AS [node()]
,tt.query(N'Sertif1') AS [node()]
FROM @xml.nodes(N'/tt') AS A(tt)
FOR XML PATH(N'tt');
作为XQuery
(现在有一个变量,但你可以直接使用root - 如上所述)
SELECT @xml.query
('
let $t:=/tt
return
<tt>
{$t/slmat}
{$t/cpost}
{$t/kodp}
{$t/gx2tov}
{$t/Sertif1}
</tt>
');
所有结果都相同......
答案 1 :(得分:0)
您可以删除和插入节点:
DECLARE @xml XML = N'<tt>
<cpost/>
<cpost/>
<gx2tov />
<kodp/>
<Sertif1/>
<Sertif1/>
<slmat/>
</tt>'
SET @xml.modify('delete tt/slmat[1]')
SET @xml.modify('insert <slmat /> as first into tt[1]')
SELECT @xml
或者,您可以重新排序所有节点:
DECLARE @xml XML = N'<tt>
<cpost/>
<cpost/>
<gx2tov />
<kodp/>
<Sertif1/>
<Sertif1/>
<slmat/>
</tt>'
SELECT
CONVERT(xml, '<' +t.value('local-name(.)','nvarchar(max)') + ' />')
FROM @xml.nodes('*/*') AS t(t)
ORDER BY t.value('local-name(.)','nvarchar(max)')
FOR XML PATH(''), TYPE, ROOT('tt')