T-SQL: Как заменить только содержимое атрибута src = 'data: image / png; base64' в теге img

Сценарий: у меня есть приложение asp.net mvc (система управления делами) с очень плохой производительностью, я обнаружил, что это приводит к плохой производительности.

Каждое действие имеет такие поля, как: «Имя действия», «Состояние активности», «Создать по» и т. Д., Которые быстро загружаются из базы данных, но у действий также есть два html-поля в базе данных с расширенными текстовыми редакторами. Некоторые пользователи напрямую вставляют изображения из буфера обмена в редакторы форматированного текста, и вставленные изображения имеют формат base64, например так:

<img src="data:image/png;base64,iVBORw0xdBXhUR...***HERE ARE 2.4 MILION SYMBOLS...***FvqlEIVCqUUL2ASUVORK5CYII=" alt="" />

некоторые атрибуты тегов img 'src' (непосредственно вставленные в редактор) содержат 2,4 миллиона символов. Я попытался выбрать только один из двух редакторов с двумя вставленными изображениями внутри, и результат запроса был выполнен за 5,38 секунды (два изображения и некоторый текст только для одной записи). Поэтому я решил найти все теги img в этих полях и заменить содержимое их атрибута src на изображение-заполнитель только для закрытых действий. Это, вероятно, положительно повлияет на производительность.

Что я должен сделать: мне нужно заменить содержимое атрибута src каждого непосредственно вставленного изображения.

Что общего между ними: каждая вставленная строка изображения начинается с 'img src = "data: image / png; base64,'.

Как они отличаются: некоторые из тегов img закрываются с помощью «>», другие с помощью «/>»

Проблема: поскольку я не знаю, как найти начало и конец только атрибута src, я попытался выбрать начало с "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(ƍB8086C1-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>

Всего 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);

--Implict преобразование преобразует ваш 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-код, объединяя doctype обратно в голый 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 . Но в вашем вопросе не было ничего об этом. Поэтому спокойный ...


Есть идеи?

10000