场景: 我有性能非常糟糕的asp.net mvc应用程序(案例管理系统),我发现它会导致性能下降。
每个活动都有诸如“活动名称”,“活动状态”,“创建依据”等字段,这些字段可以从数据库中快速加载,但是活动在带有富文本编辑器的数据库上也有两个html字段。 一些用户将图像从剪贴板直接粘贴到RTF编辑器中,粘贴的图像采用base64格式,如下所示:
<img src="data:image/png;base64,iVBORw0xdBXhUR...***HERE ARE 2.4 MILION SYMBOLS...***FvqlEIVCqUUL2ASUVORK5CYII=" alt="" />
一些img标签的“ src”属性(直接粘贴在编辑器上)包含240万个符号。我尝试仅选择其中两个粘贴图像的两个编辑器之一,执行查询结果为5.38秒(两个图像和一些文本仅用于一条记录)。因此,我决定在这些字段中查找所有img标签,并仅针对封闭活动将其src属性的内容替换为占位符图像。这可能会对性能产生积极影响。
我该怎么办: 我需要替换每个直接粘贴图像的src属性的内容。
它们之间的共同点是: 每个粘贴的图像字符串均以'img src =“ data:image / png; base64,”开头。
它们之间的区别:某些img标签用'>'关闭,另一些用'/>'
关闭问题: 因为我不知道如何仅找到src属性的开头和结尾,所以我试图选择以img标记的“ img src =“开头和img的结尾(”/>")。
select LEFT(Notes, (CHARINDEX('<img src=',Notes)-1)) +'<PATH TO PLACEHOLDER>' + RIGHT(Notes, Len(notes) - 1 - CHARINDEX('/>', Notes, CHARINDEX('<img src=',Notes))) from assignedActivity
where oid in('7B8086C1-7AF8-457C-8163-109CF167EA5E')
我会提出任何建议: 如何只替换每个src属性的内容?
以下是html编辑器内容的外观:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Some activity</title>
</head>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeIAAACxCAYAAAAYhL5OAAAgAElEQVR4AexdBXhUR9d+1y3unhBCggYvbqVAsQqFukG9pdSpUKHupe4uQFvqlEIVCqUUL24JhCQQ93X7n3d2b7LZbA7zewOWEjTzUAAAAASUVORK5CYII=" alt="" />
</body>
</html>
答案 0 :(得分:1)
使用HTML进行处理可能会很棘手,但是默认情况下,文档带有xhtml
名称空间。让我想,我们可以依靠内部结构来获得有效的XML。
您可以在此处实现此目标:
-您的样本在字符串变量中
DECLARE @html NVARCHAR(MAX)=
N'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Some activity</title>
</head>
<body>
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAeIAAACxCAYAAAAYhL5OAAAgAElEQVR4AexdBXhUR9d+1y3unhBCggYvbqVAsQqFukG9pdSpUKHupe4uQFvqlEIVCqUUL24JhCQQ93X7n3d2b7LZbA7zewOWEjTzUAAAAASUVORK5CYII=" alt="" />
</body>
</html>';
-首先,我们必须将HTML与<!DOCTYPE >
声明分开:
-我走了简单的路,并使用第一个>
来计算正确的位置,将其切成两段:
DECLARE @PosFirstClosing INT=CHARINDEX('>',@html);
DECLARE @DocType NVARCHAR(300)=SUBSTRING(@html,1,@PosFirstClosing);
-隐式转换会将HTML转换为XML。这是关键点。
-如果失败,则无法使用此方法。
-只需尝试一下并确保您的数据始终严格为 XHTML 。
DECLARE @xhtml XML=SUBSTRING(@html,@PosFirstClosing+1,4000);
-现在我们可以使用XML方法替换<img src="xyz">
的值
DECLARE @plcHolder NVARCHAR(MAX)='blah';
SET @xhtml.modify('declare namespace ns="http://www.w3.org/1999/xhtml";
replace value of (/ns:html/ns:body/ns:img/@src)[1] with sql:variable("@plcHolder")');
-在XML查看器中检查结果
SELECT @xhtml;
-现在,我们可以通过将文档类型连接回裸HTML来重建完整的html。
SET @html=@DocType + CAST(@xhtml AS NVARCHAR(MAX));
-这是结果:
SELECT @html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Some activity</title>
</head>
<body>
<img src="blah" alt=""/>
</body>
</html>
这预计将只替换一个图像源。如果其中可能有更多,或者位置可能不是/html/body/img
,则可以调整XPath
或引入一些XQuery
。但您的问题与此无关。因此随和...