html to text with domdocument class - php

How to get a html page source code without htl tags?
For example:
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="content-language" content="hu"/>
<title>this is the page title</title>
<meta name="description" content="this is the description" />
<meta name="keywords" content="k1, k2, k3, k4" />
start the body content
<!-- <div>this is comment</div> -->
open
End now one noframes tag.
<noframes><span>text</span></noframes>
<select name="select" id="select"><option>ttttt</option></select>
<div class="robots-nocontent"><span>something</span></div>
<img src="url.png" alt="this is alt attribute" />
I need this result:
this is the page title this is the description k1, k2, k3, k4 start the body content this is title attribute open End now one noframes tag. text ttttt something this is alt attribute
I need too the title and the alt attributes.
Idea?

You could do it with a regex.
$regex = '/\<.\>/';
would be a very simple start to remove anything with < and > around it. But in order to do this, you're going to have to pull in the HTML as a file_get_contents() or some other function that will turn the code into text.
Addendum:
If you want individual attributes pulled as well, you're going to have to write a more complex regex to pull that text out. For instance:
$regex2 = '/\<.(?<=(title))(\=\").(?=\")/';
Would pull out (I think... I'm still learning RegEx) any text between < and title=", assuming you had no other matching expressions before title. Again, this would be a pretty complicated regex process.

This cannot be done in an automated way. PHP cannot know which node attributes you want to omit. You'd either had to create some code that iterates over all attributes and textnodes which you can feed a map, defining when to use a node's content or you just pick what you want with XPath one by one.
An alternative would be to use XMLReader. It allows you to iterate over the entire document and define callbacks for the element names. This way, you can define what to do with what element. See
http://www.ibm.com/developerworks/library/x-pullparsingphp.html

My solution is a bit more complicate but it worked fine for me.
If you are sure that you have XHTML, you can simply consider the code as XML (but you have to put everything in a proper wrapping).
Then with XSLT you can define some basic templates that do what you need.

Related

php to strip and replace html meta tags

I'm not very familiar with PHP overall, but I'm trying to find a way to change some parts of the following documents:
index.html
hidden.html
Both pages are using the same header include file containing <meta name="robots" content="index, follow">
but I want to use PHP for some pages to strip and replace the entire line, and replace with something like <meta name="robots" content="none">
Can anyone provide an example of just stripping such a thing, and also strip+replace?
Would be greatly appreciated.
You can use str_replace to find and replace strings. See http://php.net/manual/en/function.str-replace.php
str_replace("I want to replace this", "with this");

Regular expression to get page title

There are lots of answers to this question, but not a single complete one:
With using one regular expression, how do you extract page title from <title>Page title</title>?
There are several other cases how title tags are typed, such as:
<TITLE>Page title</TITLE>
<title>
Page title</title>
<title>
Page title
</title>
<title lang="en-US">Page title</title>
...or any combination of above.
And it can be on its own line or in between other tags:
<head>
<title>Page title</title>
</head>
<head><title>Page title</title></head>
Thanks for help in advance.
UDPATE: So, the regex approach might not be the best solution to this. Which PHP based HTML parser could handle all scenarios, where HTML is well formed (or not so well)?
UPDATE 2: sp00m's regex (https://stackoverflow.com/a/13510307/1844607) seems to be working in all cases. I'll get back to this if needed.
Use a HTML parser instead. But in case of:
<title[^>]*>(.*?)</title>
Demo
Use the DOMDocument class:
$doc = new DOMDocument();
$doc->loadHTML($html);
$titles = $doc->getElementsByTagName("title");
echo $titles->item[0]->nodeValue;
Use this regex:
<title>[\s\S]*?</title>

What does these regular expressions mean in this code?

I was trying to change some parts of a joomla plugin, when I faced this part of it and I have no idea what it's doing.
Can someone please explain to me what these regular expressions and those ${4} do?
$comStart = '';
$comEnd = '';
$output = JResponse::getBody();
$output = preg_replace('/\<meta name=\"og\:/', '<meta property="og:', $output);
$output = preg_replace('/\<meta name=\"fb:admins/', '<meta property="fb:admins', $output);
$output = preg_replace('/<(\w+) (\w+)="(\w+):(\w+)" (\w+)="([a-zA-Z0-9\ \_\-\:\.\&\/\,\=\!\?]*)" \/>/i', $comStart.'<${1} ${2}="${3}:${4}" ${5}="${6}" >'.$comEnd, $output);
FYI: This plugin is for displaying facebook and opengraph tags inside articles.
SERIOUS NOTE!
The use of regular expressions to parse/match HTML/XML is highly
discouraged. Seriously, don't do it
Basically, it's a regular expression to parse/match HTML. Which may have slight side effects of not working, hard to maintain, and insanity.
The ${N} ones are called back-reference, they reference to the Nth brackets matched in the regular expressions.
If you require to do manipulation of HTML strings in PHP, you should use the DOMDocument class which was made exactly for this.
Example
<?php
$html_string = <<<HTML
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="target">
This is the target DIV! <span>This span will change texts!</span>
</div>
</body>
</html>
HTML;
$dom = new DOMDocument();
// Loading HTML from string...
$dom->loadHTML($html_string);
//Retrieve target and span elements
$target = $dom->getElementById("target");
$span = $target->getElementsByTagName("span")->item(0);
//Remove text, firstChild is the text node.
$span->removeChild($span->firstChild);
//Append new text
$span->appendChild(new DOMText("This is the new text!"));
//Change an attribute
$span->setAttribute("class", "spanny");
//Save HTML to string
$html_string = $dom->saveHTML();
echo $html_string;
Regular Expressions aren't bad, evil, or scary, they are simply the wrong tool for the job, you don't stick a nail with a jackhammer do you?
$output = preg_replace('/\<meta name=\"og\:/', '<meta property="og:', $output);
Replace the string <meta name="og: with <meta property="og:. Kind of pointless - regex is not needed here.
$output = preg_replace('/\<meta name=\"fb:admins/', '<meta property="fb:admins', $output);
Replace <meta name="fb:admins with <meta property="fb:admins. Just as pointless - regex is not needed here.
$output = preg_replace('/<(\w+) (\w+)="(\w+):(\w+)" (\w+)="([a-zA-Z0-9\ \_\-\:\.\&\/\,\=\!\?]*)" \/>/i', $comStart.'<${1} ${2}="${3}:${4}" ${5}="${6}" >'.$comEnd, $output);
Replace a string like <word1 word2="word3:word4" word5="word6withspecialcharacterslike-:.etc." /> with <word1 word2="word3:word4" word5=word6withspecialcharacterslike-:.etc." >. So it only removes a trailing slash before the closing >. Very suspect and Voodoo-like use of regex.
Also, all those regexes are highly inelegant (lots of pointless escapes, for example) and show that whoever wrote those doesn't know much about regexes. Letting something like this loose on HTML is asking for trouble.
AVOID! AVOID! AVOID!
Each (\w+) says find a word and store it. So you are doing this (in pseudocode)
find /(word1) (word2)="(word3)" (word4)="(manypossiblechars5)"/ignoring case
replace pattern with $comStart.<word1 word2="word3:word4" manypossiblechars5="word6">.$comEnd
The first one tries to replace tags of the form <meta name="og:... with <meta property="og:...
The second similarly replaces tags starting <meta name="fb:admins... with <meta property="fb:admins...
Finally, the third seems to take tags of the form <word word="word:word" word="something" \/> and wraps them with $comStart and $comEnd.
This is done by matching the parts of the tag (placing () around them) and then using backreferences such as ${4} to refer to the 4th matched part.
Here $comStart and $comEnd are set to '' so that seems a little pointless. It also manages to get rid of the closing slash for the tag at the same time, though who knows if that is intentional!
Those expressions attempt to fix the document head code by:
rewriting <meta name="og:*" to `
rewriting <meta name="fb:admins" to <meta property="fb:admins"
rewriting meta tags with a dangling slash to one without it (assuming it will always have two attributes.
This is just horrendous code, and as long as your templates don't have
those "mistakes" in them, you can throw this crap away.

Meta keyword and description REG EX issue

Im writing a program to pull the meta info from websites.
I need to write some regex to pull the text in the between the content tags.
$find = "<meta\s+name=['\"]??keywords['\"]??\s+content=['\"]??(.+)['\"]??\s*\/?>";
This works ok for meta keywords written like so:
<meta name="keywords" content="keyword, keyword, keyword" /> or like so
<meta name="keywords" content="keyword, keyword, keyword">
BuT I would like to flip it round so it can find the text inbetween the content tags in this format:
<meta content="keyword, keyword, keyword" name="keywords" /> or like so
<meta content="keyword, keyword, keyword" name="keywords" >
Anyone help? Cheers
For this purpose you could also use get_meta_tags() - a builtin PHP function which extracts <meta> tag attributes from websites (or already downloaded files):
$tags = get_meta_tags('http://www.example.com/');
print_r($tags);
Try this:
<meta[^>]*content="(?<keyword>[^"]*)"[^>]*/?>
Result:
You can also use PHP DOm
$doc=new DOMDocument();
$doc->loadHTML($htmlcontent);
$xpath= new DOMXPath($doc);
$nodelist=$xpath->query('//meta[#name='keywords']/#content');
foreach($nodelist as $node)
echo $node->nodeValue;
Using regexp works most of the time but it can not work safely on any HTML content.

How parse XML to get one tag and save another tag inside

I use DOM
extension of PHP5.3 to parse some xml document with <title> tag like this:
<title>some text <word>keyword</word> some text</title>
I want get result from tag <title> with certain tags inside it (i want know keywords that's why i want save tag <word> inside tag <title>). Result in this case must be something like this:
some text [word]keyword[/word] some text
I do some code:
$title=$doc->getElementsByTagName('title')->item(0)->nodeValue;
$title must contain some result. But I get only text without any tags inside it and I don't know now where keywords is.
some text keyword some text
I don't know how to save tag <word>!
How could I get result like some text [word]keyword[/word] some text from DOM extension?
Thanks for help.
If you want everything + the tags themselves, there's always saveXML:
http://us3.php.net/manual/en/domdocument.savexml.php
You pass the node you want and it gives you a string back, though the <title> start and end tags will be included. Also it will include attributes as well.

Categories