SQL Server 在插入时更改 XML 结构

Mr *_*ach 16 xml sql-server

我正在将一些 XML 数据插入 SQL Server 中的 XML 列,但在插入数据后,它已被 sql server 更改。这是我插入的数据

              <xsl:value-of select="name/n/given" />
            <xsl:text> </xsl:text>
          <xsl:value-of select="name/n/family" />
Run Code Online (Sandbox Code Playgroud)

当我读回来时,它看起来像这样

              <xsl:value-of select="name/n/given" />
          <xsl:text />
          <xsl:value-of select="name/n/family" />
Run Code Online (Sandbox Code Playgroud)

注意第二行。这是一个问题,因为它改变了 XSLT 转换输出的方式。第一个例子将在给定和姓氏之间创建一个空格,而第二个不会创建任何空格,所以它会像约翰约翰森,而第一个会像约翰约翰森。

有没有办法解决这个问题?

Mik*_*son 25

您可以xml:space = "preserve"在要保留空间的节点上使用。使用 xml:space 是“只是一种意图信号”,但 SQL Server 在这里对我们很好。

对于一个节点

declare @X xml =
'<root>
  <element xml:space = "preserve"> </element>
  <element> </element>
</root>'

select @X;
Run Code Online (Sandbox Code Playgroud)

结果:

<root>
  <element xml:space="preserve"> </element>
  <element />
</root>
Run Code Online (Sandbox Code Playgroud)

整个文件:

declare @X xml =
'<root xml:space = "preserve">
  <element> </element>
  <element> </element>
</root>'

select @X;
Run Code Online (Sandbox Code Playgroud)

结果:

<root xml:space="preserve">
  <element> </element>
  <element> </element>
</root>
Run Code Online (Sandbox Code Playgroud)

整个文档的另一个选项是使用convert with style 1

保留微不足道的空白。此样式设置设置默认 xml:space 处理以匹配 xml:space="preserve" 的行为。

declare @X xml = convert(xml, 
'<root>
  <element> </element>
  <element> </element>
</root>', 1)

select @X;
Run Code Online (Sandbox Code Playgroud)

  • @LightnessRacesinOrbit 我对 SQL Server 的实现非常满意。XML 中的格式(空格)在您说重要之前并不重要。看看[这个例子](https://rextester.com/EXWI82670),看看文档中实际存在的节点数以及它对存储大小的影响.. (3认同)
  • 我认为这是违反规范的,因为这里的数据被接受为 XML 并存储为 XML,除了简单地存储文档(表面上)之外,没有任何操作或转换或任何其他形式的 XML 层恶作剧,所以行为应该属于“处理器”而不是“应用程序”,因此[不得去除空格](https://www.w3.org/TR/xml/#sec-white-space)。 (3认同)

Mic*_*een 9

SQL Server 文档的这一

数据存储在一个内部表示中......可能不是文本 XML 的相同副本,因为没有保留以下信息:无关紧要的空格、属性顺序、命名空间前缀和 XML 声明。

对于您的示例,我认为它认为中间标签的空白不重要,因此可以自由地重构表示。我认为没有办法解决这个问题。这正是 SQL Server 实现 XML 数据类型的方式。

解决方法将包括使用占位符而不是@Aaron 所说的空格。消费者必须记住插入和删除这些令牌。或者将列定义为 nvarchar 而不是 XML。这肯定会保留所有空白和任何其他格式。一个简单的例子:

create table x(i nvarchar(99), j xml);
insert x values ('<a> </a>', '<a> </a>');  -- note the space
select * from x

i           j
----------  -------
<a> </a>    <a />  
Run Code Online (Sandbox Code Playgroud)

nvarchar 列保留输入格式,而 XML 列不保留。

您将无法在 SQL 查询中使用 XPATH。如果 XML 仅在应用程序中被分解,这无关紧要。此外,字符串可以被压缩以节省数据库中的空间,如果这对您很重要。