Asked  1 Year ago    Answers:  5   Viewed   14 times

i want to warp an <img> element in a <p style="text-align:center"></p>. this is the code i have so far:

$dom_err = libxml_use_internal_errors(true);
$dom = new domdocument('1.0', 'utf-8');
$dom->loadhtml(mb_convert_encoding($arr['nm_corpo_artigo'], 'html-entities', 'utf-8'));
$xpath = new domxpath($dom);
foreach ($xpath->query("//figure/img") as $img) {
    $img->setattribute('style','max-width: 100%; height: auto;');
    $img->setattribute('class','mb-4 mt-4');
}
$body = $dom->savehtml();

and this is the structure genrated by the code:

at the end iwould like to have:

<figure ...>
   <p style="text-align:center"><img ...><figcaption>...</p>
</figure ...>

...

<?xml version="1.0" standalone="yes"?>
      <!doctype html public "-//w3c//dtd html 4.0 transitional//en" "http://www.w3.org/tr/rec-html40/loose.dtd">
      <html>
        <body>
          <p>lorem ipsum dolor sit amet, consectetur adipiscing elit. mauris elementum sagittis est in vestibulum. maecenas vitae auctor nisi, id ullamcorper ex. ut l ?
          <p>praesent et ante ac dolor sagittis ultricies ac ac ligula. quisque iaculis lorem non est ornare, ornare varius justo aliquet. vestibulum quam tortor, pos ?
          <figure class="image">
            <img src="/storage/12/articles/pictures/body_1574716135628_045090d10819d1777ed93e4e1a1cf079.jpeg"/>
            <figcaption>ttttt</figcaption>
          </figure>
          <p>pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. aenean in urna nibh. quisque fermentum lobortis euismod. ut ?
          <p>in pharetra efficitur sapien, a venenatis velit. donec rutrum ut nunc nec mollis. suspendisse ac auctor purus. curabitur nec eleifend ipsum, eu aliquet t ?
          <p>vestibulum ullamcorper ante pharetra quam pharetra dictum. fusce sed turpis eget lacus pretium sollicitudin malesuada sagittis nulla. integer pulvinar or ?
        </body>
      </html>

 Answers

5

what you need to do is create a new paragraph element (with the new attribute) and replace the image tag with this new tag and then add the img tag back into the new paragraph tag...

foreach ($xpath->query("//figure/img") as $img) {
    $img->setattribute('style','max-width: 100%; height: auto;');
    $img->setattribute('class','mb-4 mt-4');
    $p = $dom->createelement("p");
    $p->setattribute('style', 'text-align:center');
    $img->parentnode->replacechild($p, $img);
    $p->appendchild($img);
}
Thursday, April 1, 2021
 
3

that's a common problem with dom : you have to do a bit more work if you want to get the content of a tag, and the content of all its children.

basically, you have to loop over the child nodes of the one you've matched with your xpath query, to get their contents.

there is a solution proposed in one one the user notes on the manual page of the domelement class -- see this note.


integrating this solution into the code you already have should give you something that looks like this for the declaration of the html string, with sub-tags :

$html = <<<html
<div class="main">
    <div class="text">
        <p>
            capture this <strong>text</strong> <em>1</em>
        </p>
        <p>
            and some other <strong>text</strong>
        </p>
    </div>
</div>
html;


and, to extract the data from that html string, you can use something like that :

$dom = new domdocument();
$dom->loadhtml($html);

$xpath = new domxpath($dom);

$tags = $xpath->query('//div[@class="main"]/div[@class="text"]');
foreach ($tags as $tag) {
    $innerhtml = '';

    // see http://fr.php.net/manual/en/class.domelement.php#86803
    $children = $tag->childnodes;
    foreach ($children as $child) {
        $tmp_doc = new domdocument();
        $tmp_doc->appendchild($tmp_doc->importnode($child,true));       
        $innerhtml .= $tmp_doc->savehtml();
    }

    var_dump(trim($innerhtml));
}

the only thing that has changed is the content of the foreach loop : instead of just using $tag->nodevalue, you have to iterate over the child elements.


which gives me the following output :

string '<p>
            capture this <strong>text</strong> <em>1</em>
        </p>


<p>
            and some other <strong>text</strong>
        </p>' (length=150)

which is the full content of the <div> tag that was matched, and all its children -- including the tags.


note : there are often interesting ideas and solution in the users notes of the manual ;-)

Thursday, April 1, 2021
 
macha
 
3
  1. locate the element you would like to interact with using your favourite browser developer tools

  2. choose an appropriate locator strategy which will allow to uniquely match the element at the page
  3. locate the element
  4. wrap the locating code into an explicit wait this way your test will be more robust and reliable
  5. use webelement apis to interact with elements

example code:

driver.get("https://www.tradingview.com/chart/")

webdriverwait(driver, 10).until(ec.element_to_be_clickable((by.xpath, "//a[contains(@class,'format')]"))).click()
input = webdriverwait(driver, 10).until(
    ec.element_to_be_clickable((by.xpath, "//input[contains(@class,'innerinput')]")))
driver.execute_script("arguments[0].value=30", input)
Wednesday, September 1, 2021
 
3

you can try this:

http://jsfiddle.net/ggjxn/1/

$(function() {
    $('h5').each(function(i, e) {
        $(e).nextuntil('h5').wrapall('<div>');
    });
});
Sunday, November 7, 2021
 
paoloP
 
2

use:

//table/tr[td/input/@name = 'email']

this means:

select all tr elements that are children of a table and that have a child td that has a child input with arrtibute name whose value is the string 'email'.

do note: no reverse axis is used in the expression.

Sunday, December 5, 2021
 
SubniC
 
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :