I'm trying to parse some HTML with DOM in PHP, but I'm having some problems. First, in case this change the solution, the HTML that I have is not a full page, rather, it's only part of it.
<!-- This is the HTML that I have --><a href='/games/'>
<div id='game'>
<img src='http://images.example.com/games.gif' width='300' height='137' border='0'>
<br><b> Game </b>
</div>
<div id='double'>
<img src='http://images.开发者_如何学运维example.com/double.gif' width='300' height='27' border='0' alt='' title=''>
</div>
</a>
Now I'm trying to get only the div with the id double
. I've tried the following code, but it doesn't seem to be working properly. What might I be doing wrong?
//The HTML has been loaded into the variable $html
$dom=new domDocument;
$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;
$keepme = $dom->getElementById('double');
$contents = '<div style="text-align:center">'.$keepme.'</a></div>';
echo $contents;
I think DOMDocument::getElementById
will not work in your case : (quoting)
For this function to work, you will need either to set some ID attributes with
DOMElement::setIdAttribute
or a DTD which defines an attribute to be of type ID.
In the later case, you will need to validate your document withDOMDocument::validate
orDOMDocument->validateOnParse
before using this function.
A solution that might work is using some XPath query to extract the element you are looking for.
First of all, let's load the HTML portion, like you first did :
$dom=new domDocument;
$dom->loadHTML($html);
var_dump($dom->saveHTML());
The var_dump
is here only to prove that the HTML portion has been loaded successfully -- judging from its output, it has.
Then, instanciate the DOMXPath
class, and use it to query for the element you want to get :
$xpath = new DOMXpath($dom);
$result = $xpath->query("//*[@id = 'double']");
$keepme = $result->item(0);
We now have to element you want ;-)
But, in order to inject its HTML content in another HTML segment, we must first get its HTML content.
I don't remember any "easy" way to do that, but something like this sould do the trick :
$tempDom = new DOMDocument();
$tempImported = $tempDom->importNode($keepme, true);
$tempDom->appendChild($tempImported);
$newHtml = $tempDom->saveHTML();
var_dump($newHtml);
And... We have the HTML content of your double
<div>
:
string '<div id="double">
<img src="http://images.example.com/double.gif" width="300" height="27" border="0" alt="" title="">
</div>
' (length=125)
Now, you just have to do whatever you want with it ;-)
From DomDocument::getElementById
For this function to work, you will need either to set some ID attributes with DOMElement::setIdAttribute or a DTD which defines an attribute to be of type ID. In the later case, you will need to validate your document with DOMDocument::validate or DOMDocument->validateOnParse before using this function.
For some additional information
- Simplify PHP DOM XML parsing - how?
- How do you parse and process HTML/XML in PHP?
And since someone will mention doing it with a Regular Expression sooner or later, here is the pattern you could use: /<div id='double'>(.*)<\/div>/simU
In addition, you could just use regular string functions to extract the div part, e.g.
$div = strstr($html, '<div id="double">');
$div = substr($div, 0, strpos($div, '</div>') + 6);
echo $div;
While I agree, you should not use RegEx or String functions for parsing HTML or XML, I find it absolutely okay to do so, as long as your only concern is to get this single div from the fragments. Keep it simple.
HTML Tidy should be capable of "correcting" broken and fragmented HTML documents, turning them into something that can be parsed with other tools
http://devzone.zend.com/article/761
The Tidy extension is new in PHP 5, and is available from PHP version 5.0b3 upward. It is based on the TidyLib library, and allows the developer to validate, repair, and parse HTML, XHTML and XML documents from within PHP.
After struggling with the same question for several hours, I came to this solution which does work for me and is relatively simple compared to what else I found online.
This solution fixes unwanted DOCTYPE and html, body tags as well as encoding issues.
$htmlContent = "<h1>This is a heading</h1><p>This is a paragraph</p>";
// 1.) Load the html
$dom = new DOMDocument();
$dom->loadHTML("<meta http-equiv='Content-Type' content='charset=utf-8' /><div>$htmlContent</div>");
// 2.) Do you logic
$dom->getElementsByTagName('h1')[0]->setAttribute('class', 'happy');
// 3.) Render the html
$wrapperNode = $dom->getElementsByTagName('div')[0];
$renderedHtml = $dom->saveHTML($wrapperNode);
// If you want to keep the wrapper div
echo $renderedHtml;
// Or remove the wrapper <div>
echo substr(trim($renderedHtml), 5, -6);
An XML document can only have one element at the root level. Probably, the HTML parser has a similar requirement. Try wrapping the content in a <body/>
tag.
Seems it's something else. This page describes what may be the cause. I'd recommend that you use XPath to get the element.
The fragment is HTML, but to be parsed through DOM it should XHTML. Every open tag must be closed.
In your case it means you should replace <br>
with <br />
and <img ... >
with <img ... />
精彩评论