我必须从存储为Subject
的{{1}}中提取电子邮件XML
。
我正在使用此查询:
nvarchar
此查询的作用是首先提取包含电子邮件主题(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
)的字符串,然后将其转换为XML,然后使用XML的<SUBJECT>....</SUBJECT>
函数获取Subject值。
这很好用,但在某些情况下,XML格式不正确并且解析失败。示例:
value
这里的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&
中逃避特殊字符!
有没有人有解决方案来解析这些错误?
答案 0 :(得分:2)
额外'&lt;'在'&lt;&gt;'中字符组合阻止了转换为XML。所以我建议你摆脱'&lt;&gt;'在将字符串转换为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)') )
一种选择是使用游标迭代查询结果。
答案 1 :(得分:2)
这些XML是如何生成的?这是你的控制吗?邪恶“&lt;,&gt;和&amp; ”的三个字符必须经过特殊处理,CDATA
或转义。如果XML生成正确,无法将它们置于禁止的地方 ......
以下是两个工作示例。第二个与里斯琼斯相同......
在第一个例子中,我替换了“&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>','<>','<>');
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)') )
答案 2 :(得分:1)
我花了一些时间来弄清楚这里出了什么问题 - 你的字符串中有单引号(第二个例子),它们需要加倍;
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)') )