Get data from div classes - php

How I can get data from div classes?
Example: A <div class=ab>1 2</div>b <div class=ab>3 4</div>c.
I want: 1 2, 3 4 etc - between <div class=ab> and </div>.
Second example: http://www.imdb.com/title/tt29747">
I want: tt29747 - between http://www.imdb.com/title/ and ">.
With strstr all good, except that I get only the first result. I tried some solutions founded here but no succes, regular expressions beyond me. Thank you!

Try parsing the HTML using DOMDocument() instead of regex.
However, here is the regex to parse assuming there will be no nested div:
$html= 'Example: Lorem <div class=ab>1 2</div>ipsum <div class=ab>3 4</div>dolor.';
preg_match_all('|<div class=ab>([^<]*)</div>|i', $html, $m);
print_r($m[1]);
And for parsing the title id:
$html = 'http://www.imdb.com/title/tt29747">';
preg_match('|imdb.com/title/(tt\d+)|i', $html, $m);
print_r($m[1]);

Related

Truncate Text Within Specific HTML Tag

This might not even be possible but I have quite a limited knowledge of PHP so I can't figure out if it is or not.
Basically I have a string $myText and this string outputs HTML in the following format:
<p>This is the main bit of text</p>
<small> This is some additional text</small>
My aim is to limit the number of characters displayed specifically within the <p> tag, for example 10 characters.
I have been playing around with PHP substr but I can only get this to work on all of the text, not just the text in the <p> tag.
Do you know if this is possible and if it is, do you know how to do it? Any pointers at all would be appreciated.
Thank you
The simplest solution is:
<?php
$text = '
<p>This is the main bit of text</p>
<small> This is some additional text</small>';
$pos = strpos($text,'<p>');
$pos2 = strpos($text,'</p>');
$text = '<p>' . substr($text,$pos+strlen('<p>'),10).substr($text,$pos2);
echo $text;
but it will work just for first pair of <p> ... </p>
If you need more, you can use regular expressions:
<?php
$text = '
<p>This is the main bit of text</p>
<small> This is some additional text</small>
<p>
werwerwrewre
</p>';
preg_match_all('#<p>(.*)</p>#isU', $text, $matches);
foreach ($matches[1] as $match) {
$text = str_replace('<p>'.$match.'</p>', '<p>'.substr($match,0,10).'</p>', $text);
}
echo $text;
or even
<?php
$text = '
<p>This is the main bit of text</p>
<small> This is some additional text</small>
<p>
werwerwrewre
</p>';
$text = preg_replace_callback('#<p>(.*)</p>#isU', function($matches) {
$matches[1] = '<p>'.substr($matches[1],0,10).'</p>';
return $matches[1];
}, $text);
echo $text;
However in those all 3 cases, all white characters are assumed as part of the string, so if the content of <p>...</p> starts with 3 spaces and you want to display only 3 characters, you simple display only 3 spaces, nothing more. Of course it can be quite easily modified, but I mentioned it to notice that fact.
And one more thing, quite possible you will need to use multibyte version of functions to get the result, so for example instead of strpos() you should use mb_strpos() and set earlier utf-8 encoding using mb_internal_encoding('UTF-8'); to make it working
You can achieve it by a quite simple way:
<?php
$max_length = 5;
$input = "<b>example: </b><div align=left>this is a test</div><div>another very very long item</div>";
$elements_count = preg_match_all("|(<[^>]+>)(.*)(</[^>]+>)|U",
$input,
$out, PREG_PATTERN_ORDER);
for($i=0; $i<$elements_count; $i++){
echo $out[1][$i].substr($out[2][$i], 0, $max_length).$out[3][$i]."\n";
}
these will work for any tag and any class or attribute within it.
ex. input:
<b>example: </b><div align=left>this is a test</div><div>another very very long item</div>
output:
<b>examp</b>
<div align=left>this </div>
<div>anoth</div>

how do I use preg_replace_callback on unknown values?

I got some great help today with starting to understand preg_replace_callback with known values. But now I want to tackle unknown values.
$string = '<p id="keepthis"> text</p><div id="foo">text</div><div id="bar">more text</div><a id="red"href="page6.php">Page 6</a><a id="green"href="page7.php">Page 7</a>';
With that as my string, how would I go about using preg_replace_callback to remove all id's from divs and a tags but keeping the id in place for the p tag?
so from my string
<p id="keepthis"> text</p>
<div id="foo">text</div>
<div id="bar">more text</div>
<a id="red"href="page6.php">Page 6</a>
<a id="green"href="page7.php">Page 7</a>
to
<p id="keepthis"> text</p>
<div>text</div>
<div>more text</div>
Page 6
Page 7
There's no need of a callback.
$string = preg_replace('/(?<=<div|<a)( *id="[^"]+")/', ' ', $string);
Live demo
However in the use of preg_replace_callback:
echo preg_replace_callback(
'/(?<=<div|<a)( *id="[^"]+")/',
function ($match)
{
return " ";
},
$string
);
Demo
For your example, the following should work:
$result = preg_replace('/(<(a|div)[^>]*\s+)id="[^"]*"\s*/', '\1', $string);
Though in general you'd better avoid parsing HTML with regular expressions and use a proper parser instead (for example load the HTML into a DOMDocument and use the removeAttribute method, like in this answer). That way you can handle variations in markup and malformed HTML much better.

Extract <span> tag contents in PHP

Say I have a WordPress post, and certain words are wrapped in span tags.
For example:
<p>John went to the <span>bakery</span> today,
and after picking up his favourite muffin
he made his way across to the <span>park</span>
and spent a couple hours on the <span>swings</span>
with his friends.</p>
Is then then a way using PHP to dynamically spit them (the words in the span tags) out as an ordered list in my template file?
Like so:
<h3>What John Did Today</h3>
<ol>
<li>bakery</li>
<li>park</li>
<li>swings</li>
</ol>
If someone could point be in the right direction of how to do something like this, it would be much appreciated. Thank you.
$str = '<p>John went to the <span>bakery</span> today, and after picking up his favourite muffin he made his way across to the <span>park</span> and spent a couple hours on the <span>swings</span> with his friends.</p>';
$d = new DomDocument;
$d->loadHTML($str);
$xpath = new DOMXPath($d);
echo "<h3>What John Did Today</h3>\n";
echo "<ol>\n";
foreach ($xpath->query('//span') as $span)
echo "<li>".$span->nodeValue."</li>\n";
echo "</ol>\n";
A simple possibility is using regular expressions, take a look at preg_match function
Parse the DOM :
http://simplehtmldom.sourceforge.net/
I'm not a regex whiz but this SHOULD do the job for replacing <span> tags with <li> tags:
$str = preg_replace("/<span>([^[]*)<\/span>/i", "<li>$1</li>", $str);
..i know this doesn't directly answer your question but it should help you with this at some point lol
EDIT: full actually working regex solution for getting all your span tags into an array and converting to list items at the same time:
// input string:
$str = '<span>Walk</span> blah <span>Drive</span> blah blee blah <span>Eat</span>';
// get array of span matches
preg_match_all("/(<span>)(.*?)(<\/span>)/i", $str, $matches, PREG_SET_ORDER);
// build array using the exact matches
foreach($matches as $val){
$spanArray[] = preg_replace("/<span>([^[]*)<\/span>/i", "<li>$1</li>", $val[0]);
}
if you then print_r($spanArray); you should get something that looks like this:
Array
(
[0] => <li>Walk</li>
[1] => <li>Drive</li>
[2] => <li>Eat</li>
)

regex php: find everything in div

I'm trying to find eveything inside a div using regexp. I'm aware that there probably is a smarter way to do this - but I've chosen regexp.
so currently my regexp pattern looks like this:
$gallery_pattern = '/<div class="gallery">([\s\S]*)<\/div>/';
And it does the trick - somewhat.
The problem is if i have two divs after each other - like this.
<div class="gallery">text to extract here</div>
<div class="gallery">text to extract from here as well</div>
I want to extract the information from both divs, but my problem, when testing, is that im not getting the text in between as a result but instead:
"text to extract here </div>
<div class="gallery">text to extract from here as well"
So to sum up. It skips the first end of the div. and continues on to the next.
The text inside the div can contain <, / and linebreaks. just so you know!
Does anyone have a simple solution to this problem? Im still a regexp novice.
You shouldn't be using regex to parse HTML when there's a convenient DOM library:
$str = '
<div class="gallery">text to extract here</div>
<div class="gallery">text to extract from here as well</div>
';
$doc = new DOMDocument();
$doc->loadHTML($str);
$divs = $doc->getElementsByTagName('div');
if ( count($divs ) ) {
foreach ( $divs as $div ) {
echo $div->nodeValue . '<br>';
}
}
What about something like this :
$str = <<<HTML
<div class="gallery">text to extract here</div>
<div class="gallery">text to extract from here as well</div>
HTML;
$matches = array();
preg_match_all('#<div[^>]*>(.*?)</div>#s', $str, $matches);
var_dump($matches[1]);
Note the '?' in the regex, so it is "not greedy".
Which will get you :
array
0 => string 'text to extract here' (length=20)
1 => string 'text to extract from here as well' (length=33)
This should work fine... If you don't have imbricated divs ; if you do... Well... actually : are you really sure you want to use rational expressions to parse HTML, which is quite not that rational itself ?
A possible answer to this problem can be found at http://simplehtmldom.sourceforge.net/
That class help me to solve similar problem quickly

How to grab the contents of HTML tags?

Hey so what I want to do is snag the content for the first paragraph. The string $blog_post contains a lot of paragraphs in the following format:
<p>Paragraph 1</p><p>Paragraph 2</p><p>Paragraph 3</p>
The problem I'm running into is that I am writing a regex to grab everything between the first <p> tag and the first closing </p> tag. However, it is grabbing the first <p> tag and the last closing </p> tag which results in me grabbing everything.
Here is my current code:
if (preg_match("/[\\s]*<p>[\\s]*(?<firstparagraph>[\\s\\S]+)[\\s]*<\\/p>[\\s\\S]*/",$blog_post,$blog_paragraph))
echo "<p>" . $blog_paragraph["firstparagraph"] . "</p>";
else
echo $blog_post;
Well, sysrqb will let you match anything in the first paragraph assuming there's no other html in the paragraph. You might want something more like this
<p>.*?</p>
Placing the ? after your * makes it non-greedy, meaning it will only match as little text as necessary before matching the </p>.
If you use preg_match, use the "U" flag to make it un-greedy.
preg_match("/<p>(.*)<\/p>/U", $blog_post, &$matches);
$matches[1] will then contain the first paragraph.
It would probably be easier and faster to use strpos() to find the position of the first
<p>
and first
</p>
then use substr() to extract the paragraph.
$paragraph_start = strpos($blog_post, '<p>');
$paragraph_end = strpos($blog_post, '</p>', $paragraph_start);
$paragraph = substr($blog_post, $paragraph_start + strlen('<p>'), $paragraph_end - $paragraph_start - strlen('<p>'));
Edit: Actually the regex in others' answers will be easier and faster... your big complex regex in the question confused me...
Using Regular Expressions for html parsing is never the right solution. You should be using XPATH for this particular case:
$string = <<<XML
<a>
<b>
<c>texto</c>
<c>cosas</c>
</b>
<d>
<c>código</c>
</d>
</a>
XML;
$xml = new SimpleXMLElement($string);
/* Busca <a><b><c> */
$resultado = $xml->xpath('//p[1]');

Categories