Мой 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;