En mi tabla, tengo una fila que contiene una cadena como esta:

<p>hello</p><p>this is patrick</p><p><img src="/assets/img/myface.jpg" width="320" height="320"/></p>

Y quiero darle a la etiqueta <img> un atributo alt. Ahora estoy bastante cerca, pero de alguna manera mi código todavía muestra 2 etiquetas <img> aunque la cadena solo tiene 1. ¿Alguien puede decirme qué estoy haciendo mal?

Este es mi código hasta ahora:

$str = '<p>hello</p><p>this is patrick</p><p><img src="/assets/img/myface.jpg" width="320" height="320"/></p>';
$new_html = '';
$dom = new DOMDocument();
$dom->loadHTML($str);
$content = $dom->getElementsByTagName('*');
foreach ($content as $i => $node)
{
  if ($node->nodeName == 'html' || $node->nodeName == 'body')
  {
    continue; // dont need to process these tags, right?
  }

  if ($node->nodeName == 'img')
  {
    $img_src = $node->getAttribute('src');
    $path_arr = explode('/', $img_src);
    $filename = $path_arr[count($path_arr)-1]; // myface.jpg

    $alt = 'blah';
    $node->setAttribute('alt', $alt);
  }

  echo $dom->saveXML($node);
}
1
dapidmini 24 sep. 2019 a las 19:57

3 respuestas

La mejor respuesta

El código ligeramente modificado a continuación hace el trabajo. Solo obtiene las etiquetas img y guarda el HTML fuera del ciclo. Tenga en cuenta que cambié la forma en que se cargó el HTML, para no incluir las etiquetas de contenedor.

<?php

$str = '<p>hello</p><p>this is patrick</p><p><img src="/assets/img/myface.jpg" width="320" height="320"/></p>';
$new_html = '';
$dom = new DOMDocument();
$dom->loadHTML($str, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$content = $dom->getElementsByTagName('img');
foreach ($content as $i => $node)
{

  $img_src = $node->getAttribute('src');
  $path_arr = explode('/', $img_src);
  $filename = $path_arr[count($path_arr)-1]; // myface.jpg

  $alt = 'blah';
  $node->setAttribute('alt', $alt);
}

echo $dom->saveHTML();
1
fonini 25 sep. 2019 a las 10:51

El problema es que cuando usas

echo $dom->saveXML($node);

En el ciclo, generará varias etiquetas y, por lo tanto, la salida no es el resultado final, sino una combinación de otras partes del documento.

Intenta cambiarlo a

echo $node->nodeName."=>".$dom->saveXML($node).PHP_EOL;

Para ver que hace.

Simplemente puede eliminar el echo actual y agregar

echo $dom->saveXML();

Después del final del ciclo.

Alternativamente, si solo desea procesar las etiquetas <img>, puede limitar el ciclo más específicamente ...

$content = $dom->getElementsByTagName('img');
foreach ($content as $i => $node)
{
    $img_src = $node->getAttribute('src');
    $path_arr = explode('/', $img_src);
    $filename = $path_arr[count($path_arr)-1]; // myface.jpg

    $alt = 'blah';
    $node->setAttribute('alt', $alt);
}
echo $dom->saveXML();
1
Nigel Ren 24 sep. 2019 a las 17:08
$content = $dom->getElementsByTagName('img');
foreach ($content as $node) {
    $img_src = $node->getAttribute('src');
    $filename = basename($img_src);

    $node->setAttribute('alt', $filename);
}

echo $dom->saveHTML();

Recorra solo las imágenes con $content = $dom->getElementsByTagName('img');

Mueva $dom->saveHTML(); después del ciclo.

Obtenga el nombre de archivo con $filename = basename($img_src);

2
kaczmen 24 sep. 2019 a las 17:20