используя php preg_replace для добавления значений src независимо от того, насколько плохо сформирован элемент img

Мой html-контент выглядит следующим образом:

<div class="preload"><img src="PRODUCTPAGE_files/like_icon_u10_normal.png" width="1" height="1"/><img src="PRODUCTPAGE_files/read_icon_u12_normal.png" width="1" height="1"/><img src="PRODUCTPAGE_files/line_u14_line.png" width="1" height="1"/> 

Это одна непрерывная длинная строка без новых строк, разделяющих каждый элемент img без каких-либо отступов.

Используемый мной код php выглядит следующим образом:

 /** * * Take in html content as string and find all the <script src="yada.js" ... > * and add $prepend to the src values except when there is http: or https: * * @param $html String The html content * @param $prepend String The prepend we expect in front of all the href in css tags * @return String The new $html content after find and replace. * */ protected static function _prependAttrForTags($html, $prepend, $tag) { if ($tag == 'css') { $element = 'link'; $attr = 'href'; } else if ($tag == 'js') { $element = 'script'; $attr = 'src'; } else if ($tag == 'img') { $element = 'img'; $attr = 'src'; } else { // wrong tag so return unchanged return $html; } // this checks for all the "yada.*" $html = preg_replace('/(<'.$element.'\b.+'.$attr.'=")(?!http)([^"]*)(".*>)/', '$1'.$prepend.'$2$3$4', $html); // this checks for all the 'yada.*' $html = preg_replace('/(<'.$element.'\b.+'.$attr.'='."'".')(?!http)([^"]*)('."'".'.*>)/', '$1'.$prepend.'$2$3$4', $html); return $html; } } 

Я хочу, чтобы моя функция работала независимо от того, насколько сильно сформирован элемент img.

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

Единственное, что он должен сделать, это добавить значение src с чем-то.

Также обратите внимание, что это preg_replace не произойдет, если значение src начинается с http.

Прямо сейчас мой код работает только в том случае, если мой контент:

 <div class="preload"> <img src="PRODUCTPAGE_files/like_icon_u10_normal.png" width="1" height="1"></img> <img src="PRODUCTPAGE_files/read_icon_u12_normal.png" width="1" height="1"/><img src="PRODUCTPAGE_files/line_u14_line.png" width="1" height="1"/><img src="PRODUCTPAGE_files/line_u15_line.png" width="1" height="1"/> 

Как вы, вероятно, можете догадаться, он успешно делает это, но только для первого элемента img, потому что он переходит к следующей строке и в конце открывающего тега img нет /.

Пожалуйста, сообщите, как улучшить мою функцию.

ОБНОВИТЬ:

Я использовал DOMDocument, и это сработало! После добавления значений src мне нужно заменить его фрагментом кода php

Итак, оригинал:

 <img src="PRODUCTPAGE_files/read_icon_u12_normal.png" width="1" height="1"/> 

После использования DOMDocument и добавления моей строки preend:

 <img src="prepended/PRODUCTPAGE_files/read_icon_u12_normal.png" width="1" height="1" /> 

Теперь мне нужно заменить все:

 <?php echo $this->Html->img('prepended/PRODUCTPAGE_files/read_icon_u12_normal.png', array('width'=>'1', height='1')); ?> 

Могу ли я использовать DOMDocument? Или мне нужно использовать preg_replace?

DomDocument был создан для анализа HTML независимо от того, как он испортился, а не для создания собственного HTML-парсера, почему бы не использовать его?

Благодаря комбинации DomDocument и XPath вы можете сделать это следующим образом:

 <?php $html = <<<HTML <script src="test"/><link href="test"/><div class="preload"><img src="PRODUCTPAGE_files/like_icon_u10_normal.png" width="1" height="1"/><img src="PRODUCTPAGE_files/read_icon_u12_normal.png" width="1" height="1"/><img src="PRODUCTPAGE_files/line_u14_line.png" width="1" height="1"/><img width="1" height="1" src="httpPRODUCTPAGE_files/line_u14_line.png"/> HTML; $doc = new DOMDocument(); @$doc->loadHTML($html); $xpath = new DOMXpath($doc); $searchTags = $xpath->query('//img | //link | //script'); $length = $searchTags->length; for ($i = 0; $i < $length; $i++) { $element = $searchTags->item($i); if ($element->tagName == 'link') $attr = 'href'; else $attr = 'src'; $src = $element->getAttribute($attr); if (!startsWith($src, 'http')) { $element->setAttribute($attr, "whatever" . $src); } } // this small function will check the start of a string // with a given term, in your case http or http:// function startsWith($haystack, $needle) { return !strncmp($haystack, $needle, strlen($needle)); } $result = $doc->saveHTML(); echo $result; 

Вот живой ДЕМО его работы.

Если ваш HTML-код испорчен, например, отсутствующие конечные теги и т. Д., Вы можете использовать до @$doc->loadHTML($html); :

 $doc->recover = true; $doc->strictErrorChecking = false; 

Если вы хотите, чтобы форматированный результат вы могли использовать до @$doc->loadHTML($html); :

 $doc->formatOutput = true; 

С XPath мы только фиксируем данные, которые вам нужно редактировать, поэтому мы не беспокоимся о других элементах.

Имейте в виду, что если у вашего HTML отсутствовали теги, например body , html , doctype , head это автоматически добавит его, но если у вас уже есть, он не должен делать ничего другого.

Однако, если вы хотите их удалить, вы можете использовать ниже, а не просто $doc->saveHTML(); :

 $result = preg_replace('~<(?:!DOCTYPE|/?(?:html|head|body))[^>]*>\s*~i', '', $doc->saveHTML()); 

Если вы хотите заменить элемент новым созданным элементом на своем месте, вы можете использовать это:

 $newElement = $doc->createElement($element->tagName, ''); $newElement->setAttribute($attr, "prepended/" . $src); $myArrayWithAttributes = array ('width' => '1', 'height' => '1'); foreach ($myArrayWithAttributes as $attribute=>$value) $newElement->setAttribute($attribute, $value); $element->parentNode->replaceChild($newElement, $element); 

Создав фрагмент:

 $frag = $doc->createDocumentFragment(); $frag->appendXML('<?php echo $this->Html->img("prepended/PRODUCTPAGE_files/read_icon_u12_normal.png", array("width"=>"1", "height"=>"1")); ?>'); $element->parentNode->replaceChild($frag, $element); 

Live DEMO.


Вы можете форматировать HTML- код :

 $tidy = tidy_parse_string($result, array( 'indent' => TRUE, 'output-xhtml' => TRUE, 'indent-spaces' => 4 )); $tidy->cleanRepair(); echo $tidy;