Remove tag p only when it contains figureimg / figure

1

I have these labels

<p><figure><img src="xxxx"></figure></p>

and I would like to change them for this, that is, remove the <p></p>

<figure><img src="xxxx"></figure>

but only when it is:

<p><figure><img></figure></p>

I tried this regular expression, but I did not get it:

<p><[^\/>][^>]*><\/[^>]+><\/p>

Could you help me please?

    
asked by skycomputer2 15.01.2018 в 22:07
source

2 answers

1

You should not use regular expressions to process HTML. Just a small change in the HTML would make your regex fail. A space of more, a change in the attributes of the tag, a comment, or more complex structures, would make even a gigantic regex not follow the rules.

It's very easy to process HTML with DOM , they are the tools that They are designed for that.


The DOM is simply generated as follows:

$html = '<p><figure><img src="xxxx"></figure></p>';

//Generar el DOM
$dom = new DOMDocument;
$libxml_opciones = LIBXML_COMPACT | LIBXML_HTML_NODEFDTD | LIBXML_NONET | LIBXML_NOERROR;
@$dom->loadHTML($html, $libxml_opciones);
//Generar un XPath para búsquedas
$xpath = new DOMXpath($dom);

And you get all the <p> with:

$p_nodelist = $dom->getElementsByTagName('p');

Then, we go through them in a loop (in reverse order to preserve the structure):

for ($i = $p_nodelist->length; --$i >= 0; ) {
    $p = $p_nodelist->item($i);

Seeing if each <p> has a single child, and that child is a <figure> :

    $p_hijos = $xpath->query('./*',$p);
    if ($p_hijos->length == 1 && $p_hijos->item(0)->tagName == 'figure') {

... doing the same with each <figure> , if you have a single child <img> .

If the conditions are verified, we replace the <p> with the <figure> son:

            $p->parentNode->replaceChild($figure,$p);

Finally, we return the DOM to a string:

$resultado = '';
foreach ($dom->documentElement->lastChild->childNodes as $elem) {
    $resultado .= $dom->saveHTML($elem);
}


Code:

<?php

$html = '<p><figure><img src="xxxx"></figure></p>';

//Generar el DOM
$dom = new DOMDocument;
$libxml_opciones = LIBXML_COMPACT | LIBXML_HTML_NODEFDTD | LIBXML_NONET | LIBXML_NOERROR;
@$dom->loadHTML($html, $libxml_opciones);
//Generar un XPath para búsquedas
$xpath = new DOMXpath($dom);


//Obtener todos los tags <p>
$p_nodelist = $dom->getElementsByTagName('p');

//Bucle para cada <p> (en orden inverso para preservar la estructura)
for ($i = $p_nodelist->length; --$i >= 0; ) {
    $p = $p_nodelist->item($i);
    $p_hijos = $xpath->query('./*',$p);

    //Si el <p> tiene un único hijo, y ese hijo es un <figure>
    if ($p_hijos->length == 1 && $p_hijos->item(0)->tagName == 'figure') {
        $figure = $p_hijos->item(0);

        //Si el <figure> tiene un único hijo, y ese hijo es una <img>
        $figure_hijos = $xpath->query('./*',$figure);
        if ($figure_hijos->length == 1 && $figure_hijos->item(0)->tagName == 'img') {

            //REEMPLAZAR todo el <p> por solamente el <figure>
            $p->parentNode->replaceChild($figure,$p);

        }
    }
}

//Guardar el html
$resultado = '';
foreach ($dom->documentElement->lastChild->childNodes as $elem) {
    $resultado .= $dom->saveHTML($elem);
}

//Imprimir el resultado
echo $resultado;

Result:

<figure><img src="xxxx"></figure>

Demo:
link

    
answered by 16.01.2018 в 01:05
1

Php code:

$str = '<p><img src="img/something.jpg" width="1249124" height="20" alt="foo" /></p>';
$str = preg_replace('%(.*?)<p>\s*(<img[^<]+?)\s*</p>(.*)%is', '$1$2$3', $str);

Source: StackOverflow.com

Demo: link

Explanation of the regular expression (translation):

Haga coincidir la expresión regular siguiente y capture su coincidencia en el número de referencia 1 «(. *?)»:

   Cualquier carácter que no sea un carácter de salto de línea «. *?» entre cero y un número ilimitado de veces.
 
   Coincidencia con "<p>", literalmente «<p>».

   Un solo carácter que sea un "carácter de espacio en blanco" (espacios, tabuladores y saltos de línea) «\ s *», entre cero y un número ilimitado de veces, tantas veces como sea posible «*».

Haga coincidir la expresión regular siguiente y capture su coincidencia en el número de referencia 2 «(<img [^ <] +?)»:

   Coincidencia con "<img" literalmente «<img».

   Cualquier elemento que NO sea un "<" «[^ <] +?», entre uno y un número ilimitado de veces «+?».

   Cualquier carácter que sea un "carácter de espacio en blanco" (espacios, pestañas y saltos de línea) «\ s *», entre cero y un número ilimitado de veces «*».

   Coincidencia con "</ p>", literalmente «</ p>».

Haga coincidir la expresión regular siguiente y capture su coincidencia en el número de referencia 3 «(. *)»:

   Cualquier carácter que no sea un carácter de salto de línea «. *», entre cero y un número ilimitado de veces «*».
    
answered by 17.01.2018 в 09:00