2016-08-19 4 views
0

これは私のXMLです。私の目標は、エクスポートのCDATAをValueノード内のデータにラップし、それをCDATAを削除したXml型の列にインポートすることです。XMLの周りにCDATAを折り返して取り除く

ShapeInfoは、XML型であるとCustomPanelは[ShapeInfoの最初のノードである今、私はテーブルからXMLで値ノード内の「データ」を交換していますし、私は私がその周りのCDataを入れています信じて
<Custom> 
    <Table>Shape</Table> 
    <Column>CustomScreen</Column> 
    <Value>Data</Value> 
<Custom> 

、 ] XML。

<Value>&lt;CustomPanel VisibilityIndicator=""&gt;&lText="No" Checked="False" Height="20" Width="50"/&gt;&lt;/Cell&gt;&lt;/Row&gt;&lt;/Table&gt;&lt;/CustomPanel&gt;</Value> 

を、私はその列

EXEC('UPDATE ['+ @tableName + '] SET [' + @columnName + '] = ''' + @nodeValue + ''' WHERE Shape_ID = ''' + @ShapeID + '''') 
に更新するために、いくつかの動的SQLをやっている:結果は情報のみの周りにCDATAを持って、私はそれを期待していても、このようになりますしかし

SET @OutputXML= replace(@OutputXML, 'Data', CAST((SELECT [ShapeInfo]  
         FROM [Shape] WHERE [Shape_ID] = @ShapeID) as VARCHAR(MAX)) 

SET @OutputXML= replace(@OutputXML, '<CustomPanel', '<![CDATA[<CustomPanel') 

私は、CDATAを削除するために以下を使用できるかもしれないと言われましたが、私はそれを使用しませんでした。

declare @x xml 
set @x=N'<Value>&lt;CustomPanel....... all the current info ...=&quot;&quot;&gt;</Value>' 

select @x.value('(/Value)[1]', 'nvarchar(max)') 

select '<![CDATA[' + @x.value('(/Value)[1]', 'nvarchar(max)') + ']]' 

再度列をチェックした後、正しい情報が含まれているようです。しかし、私はそれをVARCHARからXMLに戻したり、CDATAシンボルを削除したことはありません。では、私はここで何が欠けていますか?これは正しい方法ですか?あなたがXMLを生成を完全に制御する必要がある場合は

+0

Btw:この行 'SET @ OutputXML = replace(@OutputXML、 ' Shnugo

答えて

2

、あなたが​​を使用することができます。

DECLARE @xml xml = '<Custom> 
    <Table>Shape</Table> 
    <Column>CustomScreen</Column> 
    <Value>Data</Value> 
</Custom>'; 

WITH rawValues AS 
(
    SELECT 
     n.value('Table[1]', 'nvarchar(20)') [Table], 
     n.value('Column[1]', 'nvarchar(20)') [Column], 
     n.value('Value[1]', 'nvarchar(20)') [Value] 
    FROM @xml.nodes('Custom') X(n) 
) 
SELECT 1 AS Tag, 
     NULL AS Parent, 
     [Table] AS [Custom!1!Table!ELEMENT], 
     [Column] AS [Custom!1!Column!ELEMENT], 
     [Value] AS [Custom!1!Value!CDATA] 
FROM rawValues 
FOR XML EXPLICIT 

それは生成します。

<Custom> 
    <Table>Shape</Table> 
    <Column>CustomScreen</Column> 
    <Value><![CDATA[Data]]></Value> 
</Custom> 

あなたは、逆ソースXMLを交換し、代わりにCDATAELEMENTを使用する必要がある場合。

+0

私はこの答えが好きです。私の側からは+1ですが、AFAIC - XMLへの 'CDATA'を手探りすることについて二度考えなければなりません。ほとんどの場合、それは必要ではありません... – Shnugo

+0

私はあなたが書いた方法でそれをやろうとしたにもかかわらず、文字列の連結をやめました。 – DRockClimber

1

あなたが本当にあなたのXML内CDATAセクションが必要な場合は、2つのオプションのみ

  • 文字列の連結(非常に悪い)
  • ​​は(このケースでは、あなたがパヴェルから答えを持っている)がある

しかし、CDATAセクションが遅延入力専用であることを考慮する必要があります。 とは全く違いがありませんコンテンツがCDATAセクションに囲まれているか、適切にエスケープされているかどうか。したがって、マイクロソフトでは、最新のXML方法でCDATA構文をサポートすることさえ決定していませんでした。それはただ必要ではない。これらの例で

ルック:

が同じコンテンツを含む文字列で始まる--iは脱出し、CDATA

DECLARE @s VARCHAR(500)= 
'<root> 
<a>Normal Text</a> 
<a>Text with forbidden character &amp; &lt;&gt;</a> 
<a><![CDATA[Text with forbidden character & <>]]></a> 
</root>'; 

で - この文字列は、XMLにキャストされます。CDATAセクションでは、これ以上何もCDATAをコード化されていないことを、

DECLARE @x XML=CAST(@s AS XML); 

- この

が出力され、あなたが見ることができます。 CDATAは常に有効なエスケープされた文字列に置き換えられます。

SELECT @x; 

<root> 
    <a>Normal Text</a> 
    <a>Text with forbidden character &amp; &lt;&gt;</a> 
    <a>Text with forbidden character &amp; &lt;&gt;</a> 
</root> 

はバックキャストが--Theを明確に示し、XMLは、内部ノーCDATA任意の--Reading

SELECT CAST(@x AS VARCHAR(500)); 

<root> 
    <a>Normal Text</a> 
    <a>Text with forbidden character &amp; &lt;&gt;</a> 
    <a>Text with forbidden character &amp; &lt;&gt;</a> 
</root> 

複数のノードを持っていることをワンずつ、これはXMLのテキストの再に含まれなければならないというCDATAを使用すると主張する唯一の理由、とにかく

SELECT a.value('.','varchar(max)') 
FROM @x.nodes('/root/a') AS A(a) 

Normal Text 
Text with forbidden character & <> 
Text with forbidden character & <> 

正しい内容を示していプレゼンテーション(はXMLではありません!)は、サードパーティまたは従来の要件です。

注意:文字列連結を使用する場合は、可読性のあるCDATAのXMLを文字列形式でのみ格納できます。これをXMLにキャストすると、CDATAは省略されます。​​を使用すると、タイプセーフなストレージが可能になりますが、深いネストでは非常に扱いにくいものになります。これは、外部インタフェースを持つOKかもしれませんが、あなたはこの考え直す必要があります...関連の回答に

二つのリンク(私が:-)):

+0

@Schnugoいつものような良い情報。私は文字列の連結を終了しました。私はしかし、質問があります。 「SQLインジェクション」が発生する可能性がある場合、CDataは役に立ちませんか?ランダムなものを挿入する人々に役立つと言われました。 – DRockClimber

関連する問題