簡體   English   中英

從存儲為nvarchar的xml中提取數據

[英]Extract data from xml stored as nvarchar

我必須從存儲為nvarcharXML提取電子郵件Subject

我正在使用此查詢:

SELECT rtrim((SELECT CAST(
                    SUBSTRING(
                        [XML]
                        ,patindex('%<SUBJECT>%', [XML])
                        ,patindex('%</SUBJECT>%', [XML])-patindex('%<SUBJECT>%', [XML])+len('</SUBJECT>')
                    ) as XML).value('(/SUBJECT/OPTION)[1]','nvarchar(2000)')
            FROM   dbo.Mails 
)) as SUBJECT

該查詢要做的是首先提取包含電子郵件主題的字符串( <SUBJECT>....</SUBJECT> ),然后將其轉換為XML,然后使用XML的value函數獲取Subject值。

這可以很好地工作,但是在某些情況下,XML格式不正確且解析失敗。 范例:

DECLARE @XMLData XML =  '<SUBJECT>
      <OPTION CONSTRAINT="MASTER.IN_TITLE = ''  OR  MASTER.IN_LASTNAME = ''"><![CDATA[Découvrez nos offres de location]]>
      </OPTION>
      <OPTION CONSTRAINT="IN_TITLE <> '' AND MASTER.IN_LASTNAME <> ''"><![CDATA[~IN_TITLE~ ~IN_LASTNAME~, découvrez nos offres de location]]>
      </OPTION>
   </SUBJECT>'

select rtrim((@XMLData).value('(/SUBJECT/OPTION)[1]','nvarchar(2000)') )

Option屬性Constraint我有一個特殊字符< ,如果嘗試轉義此字符,它將轉義所有其他字符,並且丟失了XML結構。 那么如何逃脫呢?

另一個例子是這樣的:

DECLARE @XMLData XML =  '<SUBJECT>
      <OPTION NAME="DEFAULT"><![CDATA[~(IF((IN_TITLE<>'' AND IN_LASTNAME<>''),IN_TITLE&' '&IN_LASTNAME&',',''))~ nos plus belles réalisations de 2015]]>
      </OPTION>
   </SUBJECT>'

select rtrim((@XMLData).value('(/SUBJECT/OPTION)[1]','nvarchar(2000)') )

在這里,我在&IN_LASTNAME&附近出現了錯誤&IN_LASTNAME&但我認為我們不需要在CDATA轉義特殊字符!

有誰有解決方案來避免這些錯誤的解析?

“ <>”字符組合中多余的“ <”阻止了轉換為XML。 因此,我建議您在將字符串轉換為XML之前擺脫掉'<>'。 在我的示例中,我將其替換為'!='。 我意識到這可能不完全適合您的情況,因為您需要處理具有多個行而不只是一個變量的潛在查詢結果,但希望這會給您一些想法。

DECLARE @badStringPos int

DECLARE @stringXMLData varchar(500)=  '<SUBJECT>
      <OPTION CONSTRAINT="MASTER.IN_TITLE = ''  OR  MASTER.IN_LASTNAME = ''"><![CDATA[Découvrez nos offres de location]]>
      </OPTION>
      <OPTION CONSTRAINT="IN_TITLE <> '' AND MASTER.IN_LASTNAME != ''"><![CDATA[~IN_TITLE~ ~IN_LASTNAME~, découvrez nos offres de location]]>
      </OPTION>
   </SUBJECT>'

declare @XMLData xml

set @badStringPos = patindex('%<>%', @stringXMLData)

while @badStringPos <> 0
begin
    set @stringXMLData = left(@stringXMLData, patindex('%<>%', @stringXMLData) - 1) + '!=' +
                         right(@stringXMLData, len(@stringXMLData) - (patindex('%<>%', @stringXMLData) + 1))
    set @badStringPos = patindex('%<>%', @stringXMLData)
end

set @XMLData = convert(xml, @stringXMLData)

select rtrim((@XMLData).value('(/SUBJECT/OPTION)[1]','nvarchar(2000)') )

一種選擇是使用游標遍歷查詢結果。

這些XML是如何生成的? 這在您的控制之下嗎? 邪惡的三個字符“ <,>和&必須特別對待,無論是CDATA還是轉義。 如果XML生成正確,則應該不可能將它們放在禁止的地方 ...

這是兩個工作示例。 第二個與Rhys Jones相同...在第一個示例中,我將&lt;&gt;替換為“ <>” &lt;&gt;

順便說一句:顯然,在處理其他特殊字符時,應將字符串標記為N'string'才能將其讀取為unicode

DECLARE @XMLData XML =  REPLACE(N'<SUBJECT>
      <OPTION CONSTRAINT="MASTER.IN_TITLE = ''  OR  MASTER.IN_LASTNAME = ''"><![CDATA[Découvrez nos offres de location]]>
      </OPTION>
      <OPTION CONSTRAINT="IN_TITLE <> '' AND MASTER.IN_LASTNAME <> ''"><![CDATA[~IN_TITLE~ ~IN_LASTNAME~, découvrez nos offres de location]]>
      </OPTION>
   </SUBJECT>','<>','&lt;&gt;');

select rtrim((@XMLData).value('(/SUBJECT/OPTION)[1]','nvarchar(2000)') );
GO

DECLARE @XMLData XML =  N'<SUBJECT>
      <OPTION NAME="DEFAULT"><![CDATA[~(IF((IN_TITLE<>'''' AND IN_LASTNAME<>''''),IN_TITLE&'' ''&IN_LASTNAME&'','',''''))~ nos plus belles réalisations de 2015]]>
      </OPTION>
   </SUBJECT>'

select rtrim((@XMLData).value('(/SUBJECT/OPTION)[1]','nvarchar(2000)') )

花了我一段時間找出問題所在-字符串中有單引號(第二個示例),需要將它們加倍。

DECLARE @XMLData XML =  '<SUBJECT>
      <OPTION NAME="DEFAULT"><![CDATA[~(IF((IN_TITLE<>'' AND IN_LASTNAME<>''),IN_TITLE&'' ''&IN_LASTNAME&'','',''))~ nos plus belles réalisations de 2015]]>
      </OPTION>
   </SUBJECT>'

select rtrim((@XMLData).value('(/SUBJECT/OPTION)[1]','nvarchar(2000)') )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM