[英]Extract data from xml stored as nvarchar
我必須從存儲為nvarchar
的XML
提取電子郵件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相同...在第一個示例中,我將<>
替換為“ <>” <>
。
順便說一句:顯然,在處理其他特殊字符時,應將字符串標記為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>','<>','<>');
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.