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

Сценарий: У меня есть приложение 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('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>

1 Ответ

1 голос
/ 17 мая 2019

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

...