SQLサーバーは挿入時にXML構造を変更します


15

SQLサーバーのXML列にXMLデータを挿入していますが、データが挿入された後、SQLサーバーによって変更されています。ここに私が挿入するデータがあります

              <xsl:value-of select="name/n/given" />
            <xsl:text> </xsl:text>
          <xsl:value-of select="name/n/family" />

読み返すとこんな感じ

              <xsl:value-of select="name/n/given" />
          <xsl:text />
          <xsl:value-of select="name/n/family" />

2行目に注意してください。XSLT変換の出力方法が変わるため、これは問題です。最初の例では、名と姓の間にスペースが作成されますが、2番目の例ではスペースが作成されないため、JohnJohnsenのようになり、最初の例ではJohn Johnsenのようになります。

これを解決する方法はありますか?


これは問題です。XSLT変換の出力がどのようになるかが変わるからです。第二は、間にスペースを作成しませんしながら、最初のものはジョン・ヨンセンのようになる一方で、それは、JohnJohnsenようになりますので、最初の行は、与えられたと姓の間にスペースを作成します
ミスターザック

うーん、適切なスペースは ""ですが、このコメントのようなスペースだけではありません(表示されません)
a_vlad

1
おそらく、データに存在しない制御文字(_またはなど~)を使用し、それをプレゼンテーション時にスペースに置き換えることができます。
アーロンバートランド

回答:


25

xml:space = "preserve"スペースを保持するノードで使用できます。xml:spaceの使用は「意図のシグナルのみ」ですが、ここではSQLサーバーは親切です。

1つのノード

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

select @X;

結果:

<root>
  <element xml:space="preserve"> </element>
  <element />
</root>

文書全体:

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

select @X;

結果:

<root xml:space="preserve">
  <element> </element>
  <element> </element>
</root>

文書全体の別のオプションは、スタイル1で変換を使用することです。

重要でない空白を保持します。このスタイル設定は、xml:space = "preserve"の動作に合わせてデフォルトのxml:space処理を設定します。

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

select @X;

興味深いことに、これは必須です。どの空白が「重要でない」かを決定し、ドキュメントを変更せずに静かに削除することは、SQL Serverの権限ではありません。
ライトネスレースとモニカ

3
@LightnessRacesinOrbit SQL Serverによる実装に非常に満足しています。XMLでの書式設定(空白)は、言うまでは重要ではありません。見て、この例 ..文書とそれがストレージサイズにしに実際にあるノード数を確認するために
ミカエル・エリクソン

3
ここでは、データはXMLとして受け入れられ、XMLとして保存され、操作や変換、または単にドキュメントを保存する(表向き)以外のXMLレイヤーのシェナンガンを行わずにXMLとして保存されるため、仕様違反と見なします。 「アプリケーション」ではなく「プロセッサ」に分類されるため、空白を削除しないでください
モニカとの軽さレース

9

SQL Serverのドキュメントのこのページには、

データは、次の情報が保持されないため、テキストXMLの同一コピーではない可能性のある内部表現に格納されます:わずかな空白、属性の順序、名前空間プレフィックス、およびXML宣言。

あなたの例では、真ん中のタグの空白は重要ではないと考えているため、表現を自由にリファクタリングできると思います。これに対する修正はないと思います。SQL ServerがXMLデータ型を実装する方法です。

回避策には、@ Aaronが言うように、空白の代わりにプレースホルダーを使用することが含まれます。消費者は、これらのトークンを挿入して削除することを忘れないでください。または、列をXMLではなくnvarcharとして定義します。これにより、すべての空白とその他の書式設定が確実に保持されます。簡単な例:

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 />  

nvarchar列は入力形式を保持しますが、XML列は保持しません。

SQLクエリでXPATHを使用する機能が失われます。XMLがアプリケーション内でのみ細断される場合、これは重要ではありません。さらに、文字列を圧縮してDBのスペースを節約することもできます(これが重要な場合)。


XMLバージョンに対するクエリでXPATHを使用できるのは、わずかなスペースのヒット(またはミス)に依存していない限り、単に再フォーマットさせただけでもかまいません。
アーロンバートランド

0

CDATAデータを保存するときにスペースをラップできます:

<xsl:text><![CDATA[ ]]></xsl:text>

SQLサーバーは内部的にスペースを保持しているように見えますCDATAが、を使用して結果を取得するときに不要なマークアップ自体を削除しSELECTます。幸いなことに、次のような結果を再利用するときにスペースが保持されSELECTます。

DECLARE @X XML = '<text><![CDATA[ ]]></text>'
DECLARE @Y XML

SET @Y = (SELECT @X)

SELECT @Y

結果は次のようになります。

<text> </text>

CDATAも試しましたが、削除されました。
ザック氏

@MrZach CDATA自体は削除されますが、スペースは残ります。(SQL Express 2016で試用。)
ブルーノ

奇妙なことに、ここではスペースが削除されました。また、2016年または2017年表現だと思う
ミスターザック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.