It should be very simple. I am loading in php via DOMDocument();
$doc = new DOMDocument();
$doc->loadHTML($html);
$el = $doc->getElementById('somethingId');
Lets say i have
<html><head></head><body><div id="somethingId">my
<span style="background:red">something else</span>
information</div></body></html>
Q1. How to echo whats inside that element ("my information") from $el?
Q2. How to echo whats inside and including span data (like innerHTML in javascript)?
Answer to Q2:
$children = $el->childNodes;
foreach ($children as $child) {
$innerHTML .= $child->ownerDocument->saveXML( $child );
}
echo $innerHTML
You should do
echo ($el->nodeValue);
if (!is_null($el)) {
$content = $el->nodeValue;
if (empty($content)) {
$content = $el->textContent;
}
echo $content;
}
Related
I have HTML code:
<div>
<h1>Header</h1>
<code><p>First code</p></code>
<p>Next example</p>
<code><b>Second example</b></code>
</div>
Using PHP I want replace all < symbols located in code elements for example above code I want converted to:
<div>
<h1>Header</h1>
<code><p>First code</p></code>
<p>Next example</p>
<code><b>Second example</b></code>
</div>
I try using PHP DomDocument class but my work was ineffective. Below is my code:
$dom = new DOMDocument();
$dom->loadHTML($content);
$innerHTML= '';
$tmp = '';
if(count($dom->getElementsByTagName('*'))){
foreach ($dom->getElementsByTagName('*') as $child) {
if($child->tagName == 'code'){
$tmp = $child->ownerDocument->saveXML( $child);
$innerHTML .= htmlentities($tmp);
}
else{
$innerHTML .= $child->ownerDocument->saveXML($child);
}
}
}
So, you're iterating over the markup properly, and your use of saveXML() was close to what you want, but nowhere in your code do you try to actually change the contents of the element. This should work:
<?php
$content='<div>
<h1>Header</h1>
<code><p>First code</p></code>
<p>Next example</p>
<code><b>Second example</b></code>
</div>';
$dom = new DOMDocument();
$dom->loadHTML($content, LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);
foreach ($dom->getElementsByTagName('code') as $child) {
// get the markup of the children
$html = implode(array_map([$child->ownerDocument,"saveHTML"], iterator_to_array($child->childNodes)));
// create a node from the string
$text = $dom->createTextNode($html);
// remove existing child nodes
foreach ($child->childNodes as $node) {
$child->removeChild($node);
}
// append the new text node - escaping is done automatically
$child->appendChild($text);
}
echo $dom->saveHTML();
See here: https://ideone.com/bjs3IC
Why does the newline correctly display with the spans but not imgs ?
<?php
outputImages();
outputSpans();
function outputImages(){
$html = "<div class='test'>
<pre>
<img src='http://d...content-available-to-author-only...e.com/5x5/000/fff'>
<img src='http://d...content-available-to-author-only...e.com/5x5/000/fff'>
<img src='http://d...content-available-to-author-only...e.com/5x5/000/fff'>
</pre>
</div>";
getHtml($html);
}
function outputSpans(){
$html = "<div class='test'>
<pre>
<span>a</span>
<span>b</span>
<span>c</span>
</pre>
</div>";
getHtml($html);
}
function getHtml($html){
$doc = new DOMDocument;
$doc->loadhtml($html);
$xpath = new DOMXPath($doc);
$tags = $xpath->query('//div[#class="test"]');
print(get_inner_html($tags[0]));
}
function get_inner_html( $node ) {
$innerHTML= '';
$children = $node->childNodes;
foreach ($children as $child) {
$innerHTML .= $child->ownerDocument->saveXML( $child );
}
return $innerHTML;
}
The DOMDocument::loadHTML function has a second options parameter. It appears like the LIBXML_NOBLANKS is (at least one of) the default values there.
You can use
$doc->loadhtml($html, LIBXML_NOEMPTYTAG);
To override that default value and your code will work the same for the two samples.
p.s.
Not sure why you use
print(get_inner_html($tags[0]));
The $tags variable is a DOMNodeList, so you should use $tags->item(0) to get the first tag.
Your complete code should look like this:
outputImages();
outputSpans();
function outputImages() {
$html = "<div class='test'>
<pre>
<img src='http://d...content-available-to-author-only...e.com/5x5/000/fff'>
<img src='http://d...content-available-to-author-only...e.com/5x5/000/fff'>
<img src='http://d...content-available-to-author-only...e.com/5x5/000/fff'>
</pre>
</div>";
getHtml($html);
}
function outputSpans() {
$html = "<div class='test'>
<pre>
<span>a</span>
<span>b</span>
<span>c</span>
</pre>
</div>";
getHtml($html);
}
function getHtml($html) {
$doc = new DOMDocument;
$doc->loadHTML($html, LIBXML_NOEMPTYTAG);
$xpath = new DOMXPath($doc);
$tags = $xpath->query('//div[#class="test"]');
print(get_inner_html($tags->item(0)));
}
function get_inner_html( $node ) {
$innerHTML= '';
$children = $node->childNodes;
foreach ($children as $child) {
$innerHTML .= $child->ownerDocument->saveXML( $child );
}
return $innerHTML;
}
I'm trying to get the href of all anchor(a) tags using this code
$obj = json_decode($client->getResponse()->getContent());
$dom = new DOMDocument;
if($dom->loadHTML(htmlentities($obj->data->partial))) {
foreach ($dom->getElementsByTagName('a') as $node) {
echo $dom->saveHtml($node), PHP_EOL;
echo $node->getAttribute('href');
}
}
where the returned JSON is like here but it doesn't echo anything. The HTML does have a tags but the foreach is never run. What am I doing wrong?
Just remove that htmlentities(). It will work just fine.
$contents = file_get_contents('http://jsonblob.com/api/jsonBlob/54a7ff55e4b0c95108d9dfec');
$obj = json_decode($contents);
$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTML($obj->data->partial);
libxml_clear_errors();
foreach ($dom->getElementsByTagName('a') as $node) {
echo $dom->saveHTML($node) . '<br/>';
echo $node->getAttribute('href') . '<br/>';
}
I'm trying to save the result of getElementById using PHP.
The code I have:
<?php
$doc = new DOMDocument();
$doc->validateOnParse = true;
#$doc->loadHTMLfile('test.htm');
$div = $doc->getElementById('storytext');
echo $doc->saveHTML($div);
?>
This displays the relevant text, I now want to save that to a new file, I have tried using save(), saveHTMLfile() and file_put_contents(), none of those work because they only save strings and I cannot turn $div into a string, so I'm stuck.
If I just save the entire thing:
$doc->saveHTMLfile('name.ext');
It works but it saves everything, not just the part that I need.
I'm a complete DOM noob so I may be missing something very simple but I can't really find much about this through my searches.
function getInnerHtml( $node ) {
$innerHTML= '';
$children = $node->childNodes;
foreach ($children as $child) {
$innerHTML .= $child->ownerDocument->saveXML( $child );
}
return $innerHTML;
}
$html = getInnerHtml($div);
file_put_contents("name.ext", $html);
I have the following html
$html = '<body><div style="font-color:#000">Hello</div>
<span style="what">My name is rasid</span><div>new to you
</div><div style="rashid">New here</div></body>';
$dom = new DOMDocument();
$dom->loadHTML($html);
$elements = $dom->getElementsByTagName('body');
I have tried
foreach($elements as $child)
{
echo $child->nodeName;
}
The Ouput is
body
But I need to loop through all the tags under body not the body. How can I do that.
I have also tried in above example to replace
$elements = $dom->getElementsByTagName('body');
with
$elements = $dom->getElementsByTagName('body')->item(0);
But It gives Error. Any Solution??
try this
$elements = $dom->getElementsByTagName('*');
$i = 1; //counter to output from 3rd one, since foreach loop below will output" html body div span div div"
foreach($elements as $child)
{
if ($i > 2) echo $child->nodeName."<br>"; //output "div span div div"
++$i;
}
If you only want child nodes of the body element, you can use:
$body = $dom->getElementsByTagName( 'body' )->item( 0 );
foreach( $body->childNodes as $node )
{
echo $node->nodeName . PHP_EOL;
}
If you want all descending nodes of the body element, you could use DOMXPath:
$xpath = new DOMXPath( $dom );
$bodyDescendants = $xpath->query( '//body//node()' );
foreach( $bodyDescendants as $node )
{
echo $node->nodeName . PHP_EOL;
}
use this code
$elements = $dom->getElementsByTagName('*');
foreach($elements as $child)
{
echo $child->nodeName;
}