I have a div called
<div id="form">Content</div>
and I want to replace the content of the div with new content using Preg_replace.
what Regex should be used.?
You shouldn't be using a regex at all. HTML can come in many forms, and you would need to take all of them in account. What if the id/class doesn't come in the place you expect? The regex would have to be really complex to get you reasonable results.
Instead, you should use a DOM parser - or a really cool tool I recently stumbled across, phpQuery. With it, you can access your document in PHP almost exactly as you would with jQuery.
This will work in your case:
$html = '<div id="content">Content</div>';
$html = preg_replace('/(<\s*div[^>]*>)[^<]*(<\s*\/div\s*>)/', '$1New Content$2', $html);
echo $html; // <div id="content">New Content</div>
However note that since HTML is not a regular language it is impossible to handle all cases. The simple regex I provided will produce bad output in the following example:
<div class=">">Content</div>
Related
I have a situation in which I think I may have to use regex to alter html tag content or src based on the class attribute.
To document I will be parsing will be either nicely formed html, partial html or php files.
EG I would need to change/fill these tags with inner content: fileX.php
<?php
echo <<<_END
<div class="identifyingClass1"></div>
<div class="identifyingClass2"><span>holding content</span></div>
<img src='http://source.com/to/change' class='identifyingClass3' alt='descrip'/>
_END;
Resulting fileX.php
<?php
echo <<<_END
<div class="identifyingClass1">New content jsd soisvkbsdv</div>
<div class="identifyingClass2">More new content</div>
<img src='new/source.tiff' class='identifyingClass3' alt='descrip'/>
_END;
The html could be complete, could be separated by php, be as is, be inside a hereDOC...
Is the best way to achieve this to just use regex or has anyone seen or used a class for this kind of thing?
Regex is evil for such case. Better you work on the generated html. Here's how you do it.
Enable output buffering. On the ob_start function add your own callback. Process the generated html with DOMDocument inside the handler. Something like this,
function my_handler($contents){
$doc = DOMDocument::loadHTML ($contents);
// change your document here and return it later
return $doc->saveHTML();
}
ob_start('my_handler');
As already stated, RegEx is not recommended for doing such kind of things. Look at this excellent answer. My personal favourite is SimleDom which provides a jQuery-like syntax and makes working with HTML in PHP actually joyful ;).
I have this block of html:
<div>
<p>First, nested paragraph</p>
</div>
<p>First, non-nested paragraph.</p>
<p>Second paragraph.</p>
<p>Last paragraph.</p>
I'm trying to select the first, non-nested paragraph in that block. I'm using PHP's (perl style) preg_match to find it, but can't seem to figure out how to ignore the p tag contained within the div.
This is what I have so far, but it selects the contents of the first paragraph contained above.
/<p>(.+?)<\/p>/is
Thanks!
EDIT
Unfortunately, I don't have the luxury of a DOM Parser.
I completely appreciate the suggestions to not use RegEx to parse HTML, but that's not really helping my particular use case. I have a very controlled case where an internal application generated structured text. I'm trying to replace some text if it matches a certain pattern. This is a simplified case where I'm trying to ignore text nested within other text and HTML was the simplest case I could think of to explain. My actual case looks something a little more like this (But a lot more data and minified):
#[BILLINGCODE|12345|11|15|2001|15|26|50]#
[ITEM1|{{Escaped Description}}|1|1|4031|NONE|15]
#[{{Additional Details }}]#
[ITEM2|{{Escaped Description}}|3|1|7331|NONE|15]
[ITEM3|{{Escaped Description}}|1|1|9431|NONE|15]
[ITEM4|{{Escaped Description}}|1|1|5131|NONE|15]
I have to reformat a certain column of certain rows to a ton of rows similar to that. Helping my first question would help actual project.
Your regex won't work. Even if you had only non nested paragraph, your capturing parentheses would match First, non-nested ... Last paragraph..
Try:
<([^>]+)>([^<]*<(?!/?\1)[^<]*)*<\1>
and grab \2 if \1 is p.
But an HTML parser would do a better job of that imho.
How about something like this?
<p>([^<>]+)<\/p>(?=(<[^\/]|$))
Does a look-ahead to make sure it is not inside a closing tag; but can be at the end of a string. There is probably a better way to look for what is in the paragraph tags but you need to avoid being too greedy (a .+? will not suffice).
Use a two three step process. First, pray that everything is well formed. Second, First, remove everything that is nested.
s{<div>.*?</div>}{}g; # HTML example
s/#.*?#//g; # 2nd example
Then get your result. Everything that is left is now not nested.
$result = m{<p>(.*?)</p>}; # HTML example
$result = m{\[(.*?)\]}; # 2nd example
(this is Perl. Don't know how different it would look in PHP).
"You shouldn't use regex to parse HTML."
It is what everybody says but nobody really offers an example of how to actually do it, they just preach it. Well, thanks to some motivation from Levi Morrison I decided to read into DomDocument and figure out how to do it.
To everybody that says "Oh, it is too hard to learn the parser, I'll just use regex." Well, I've never done anything with DomDocument or XPath before and this took me 10 minutes. Go read the docs on DomDocument and parse HTML the way you're supposed to.
$myHtml = <<<MARKUP
<html>
<head>
<title>something</title></head>
<body>
<div>
<p>not valid</p>
</div>
<p>is valid</p>
<p>is not valid</p>
<p>is not valid either</p>
<div>
<p>definitely not valid</p>
</div>
</body>
</html>
MARKUP;
$DomDocument = new DOMDocument();
$DomDocument->loadHTML($myHtml);
$DomXPath = new DOMXPath($DomDocument);
$nodeList = $DomXPath->query('body/p');
$yourNode = $DomDocument->saveHtml($nodeList->item(0));
var_dump($yourNode)
// output '<p>is valid</p>'
You might want to have a look at this post about parsing HTML with Regex.
Because HTML is not a regular language (and Regular Expressions are), you can't pares out arbitrary chunks of HTML using Regex. Use an HTML parser, it'll get the job done considerably more smoothly than trying to hack together some regex.
I'm grabbing data from a published google spreadsheet, and all I want is the information inside of the content div (<div id="content">...</div>)
I know that the content starts off as <div id="content"> and ends as </div><div id="footer">
What's the best / most efficient way to grab the part of the DOM that is inside there? I was thinking regular expression (see my example below) but it is not working and I'm not sure if it that efficient...
header('Content-type: text/plain');
$foo = file_get_contents('https://docs.google.com/spreadsheet/pub?key=0Ahuij-1M3dgvdG8waTB0UWJDT3NsUEdqNVJTWXJNaFE&single=true&gid=0&output=html&ndplr=1');
$start = '<div id="content">';
$end = '<div id="footer">';
$foo = preg_replace("#$start(.*?)$end#",'$1',$foo);
echo $foo;
UPDATE
I guess another question I have is basically about if it is just simpler and easier to use regex with start and end points rather than trying to parse through a DOM which might have errors and then extract the piece I need. Seems like regex would be the way to go but would love to hear your opinions.
Try changing your regex to $foo = preg_replace("#$start(.*?)$end#s",'$1',$foo); , the s modifier changes the . to include new lines. As it is, your regex would have to all the content between the tags on the same line to match.
If your HTML page is any more complex than that, then regex probably won't cut it and you'd need to look into a parser like DOMDocument or Simple HTML DOM
if you have a lot to do, I would recommend you take a look at http://simplehtmldom.sourceforge.net
really good for this sort of thing.
Do not use regex, it can fail.
Use PHP's inbuilt DOM parse :
http://php.net/manual/en/class.domdocument.php
You can easily traverse and parse relevant content .
First I'll show you a sample of the code I'm working with:
<div class="entry">
<p>Any HTML content could go here!</p>
</div>
</div><!--/post -->
Normally I'd use a regex rule such as the following to look for a prefix and a suffix and grab everything in between:
(?<=<div class="entry">).*(?=</div><!--/post -->)
However, that doesnt appear to be working as it seems to be pulling the white space in between then following parts instead of the HTML content itself:
<div class="entry">
<p>
Any help/suggestions would be much appreciated as I've been bashing my head with this one for a good few hours now.
Many thanks in advance.
Don't use Regex to parse HTML. You need an Xml Parser or similar.
Search Stackoverflow for the best one, like so: Robust and Mature HTML Parser for PHP
You can also consider php strip_tags().
How can I look for links in HTML and remove them?
$html = '<p>Test Title 1</p>';
$html .= '<p>Test Title 2</p>';
$html .= '<p>Test Title 3</p>';
$match = '<a href="javascript:doThis('Test Title 2')">';
I want to remove the anchor but display the text. see below.
Test Title 1
Test Title 2
Test Title 3
I've never used Regular Expressions before, but maybe i can avoid it also. Let me know if im not clear.
Thanks
Mark
EDIT: its not a client side thing. I cant use javascript for this. I have a custom CMS and want to edit HTML stored in a Database.
You may try the simplest thing:
echo strip_tags($html, '<p>');
This strips all tags except <p>
If you really like regexp:
echo preg_replace('=</?a(\s[^>]*)?>=ims', '', $html);
EDIT:
Delete a - tag AND surrounding tags (code gets messy and doesn't work with broken (X)HTML):
echo preg_replace('=<([a-z]+)[^>]*>\s*<a(\s[^>]*)?>(.*?)</a>\s*</\\1>=ims', '$3', $html);
Howerwer if your problem is that complicated, I recommend that you try xpath.
You could see if Simple HTML DOM does the trick.
You might have some joy with Beautiful Soup - http://www.crummy.com/software/BeautifulSoup/ (Python HTML parsing / manipulation API)
sed -i -e 's/<a.*<\/a>//g' filename.html
Note that using regular expressions for hacking HTML is a... dubious proposition, but it might just work in practice ;-)
You can use
var foo = document.getElementsByTagName('a');
to fetch all the link tags. No need for regular expressions here...
EDIT: I'm just learning to read... ;) Go with PHP's DOM or XML abilities. It should be pretty easy using those.
open the HTML file in Microsoft Expression.
Ctrl+F and then chose replace tag or tag attributes contents
Easy and quick solution
Thanks
Shomaail