Remove the closing </ span> from the expression contains more than one - php

There is a very large piece of code that does not work out well when specific syntax html.
There is an expression:
<span class="*0">
<span class="*1">TEXT</span>
...
<span class="*2">TEXT</span>
</span>
There is a regular expression:
$mstr = '#<span class="0">(.*?)</span>#';
What is needed:
Cut the upper span (<span class = "* 0">) with the correct closing tag.
My regular cuts out the first in a row :(

Here is a solution. I don't know if it fits your needs, but it does the job. It simply looks for all the starting tags and closing tags, stores their substring positions and pairs them. Then it removes the tag with the class you need.
One note: if a tag is not propperly closed, this could fail. So I would suggest you build in some safety measures.
$start_pos=stripos($var,'<span class="*0">');
$len=strlen($var);
$str_len=strlen('<span class="*0">');
$offset=0;
do{
$p=stripos($var,'<span',$offset);
if($p===false){break;}
$open_pos[]=$p;
$offset=$p+1;
}while($offset<$len);
$offset=0;
do{
$p=stripos($var,'</span>',$offset);
if($p===false){break;}
$close_pos[]=$p;
$offset=$p+1;
}while($offset<$len);
$t=0;
do{
$change=false;
for($i=0;$i<count($open_pos)-1;$i++){
foreach($close_pos as $k=>$v){
if($open_pos[$i+1]>$v){
if($open_pos[$i]==$start_pos){
$end_pos=$v;
break 3;
}
unset($open_pos[$i],$close_pos[$k]);
$open_pos=array_values($open_pos);
$close_pos=array_values($close_pos);
$change=true;
break 2;
}
}
}
if($open_pos[$i]!=$start_pos){
unset($open_pos[$i],$close_pos[0]);
$open_pos=array_values($open_pos);
$close_pos=array_values($close_pos);
$change=true;
}
else{
$end_pos=$close_pos[0];
break 3;
}
if(count($open_pos)<2)break;
$t++;
}while($t<1000);
$var=substr_replace($var,'###',$end_pos,7);
$var=substr_replace($var,'###',$start_pos,$str_len);
echo $var;
Tested on this beautiful HTML:
$var='<span class="*A">a
<span class="*B">b
<span class="*E">e</span>
<span class="*C">c
<span class="*D">d
<span class="*E">e</span>
<span class="*0">BEFORE THIS ONE
<span class="*F">a</span>
<span class="*G">g
<span class="*H">h
<span class="*J">j</span>
</span>
<span class="*K">k</span>
<span class="*L">l</span>
<span class="*M">m</span>
_GGG</span>
<span class="*N">n</span>
BETWEEN</span>BETWEEN
<span class="*O">o
<span class="*P">p</span>
_OOO</span>
</span>
_CCC</span>
<span class="*Q">q
<span class="*R">r</span>
_RRR</span>
</span>
</span>
';

Related

Wrap multiple span tags within specific div using preg_replace

I have HTML code like this:
<li class="recipe-ingredient">
<span class="recipe-ingredient-quantity-unit">
<span data-original="" data-fraction="" data-normalized="0" class="recipe-ingredient-quantity recipe-ingredient-quantity"></span>
<span data-original="" class="recipe-ingredient-unit recipe-ingredient-unit"></span>
</span>
<span class="recipe-ingredient-name recipe-ingredient-name">water</span>
<span class="recipe-ingredient-notes recipe-ingredient-notes">For Kneading</span>
</li>
Using preg_replace, I want to wrap first set of <span> within one <div> and last two sets of <span> within another <div>, so my final outcome would be:
<li class="recipe-ingredient">
<div class="ing-qt-unit">
<span class="recipe-ingredient-quantity-unit">
<span data-original="" data-fraction="" data-normalized="0" class="recipe-ingredient-quantity recipe-ingredient-quantity"></span>
<span data-original="" class="recipe-ingredient-unit recipe-ingredient-unit"></span>
</span>
</div>
<div class="ing-name-notes">
<span class="recipe-ingredient-name recipe-ingredient-name">water</span>
<span class="recipe-ingredient-notes recipe-ingredient-notes">For Kneading</span>
</div>
</li>
This first one should catch the first set:
<span class[^>]+>(?:[^<]+<[^>]+>[^<]*<[^>]+>)*[^<]*</span>
And this one should catch the second set:
<span class[^>]+>(?:[^<]*<[^>]+>[^<]+<[^>]+>)*[^<]*</span>
Use it like this to avoid escaping:
$re = "#<span class[^>]+>(?:[^<]*<[^>]+>[^<]+<[^>]+>)*[^<]*</span>#im";
The replacement should be something like "<div class="ing-name-notes">$0</div>".

Changing the presentation of a query

I have this code to output records from a database
<?php
include 'database_conn.php'; // make db connection
$sql = "SELECT filmID, title, categoryName, notes FROM film";
$queryresult = mysqli_query($conn, $sql) or die(mysqli_error($conn));
while ($row = mysqli_fetch_assoc($queryresult)) {
$filmID = $row['filmID'];
$filmTitle = $row['title'];
$filmCat = $row['categoryName'];
$filmNotes = $row['notes'];
echo "<div>$filmID, $filmTitle, $filmCat, $filmNotes</div>";
}
mysqli_free_result($queryresult);
mysqli_close($conn);
?>
but to be able to remove commas and format the display of the content I need to change...
echo "<div>$filmID, $filmTitle, $filmCat, $filmNotes</div>";
to...
echo
"<div class="film">
<span class="filmID">5</span>
<span class="title">my darling clementine</span>
<span class="category">epic</span>
<span class="notes">Henry Fonda</span>
</div>";
I keep getting an error when submitting the form saying (Parse error: syntax error, unexpected '<' in /home/unn_w15025267/public_html/chollerton.php on line 45)
Line 45 is:
"<div class="film">
Records currently look like this:
Patrick, Bloggs, 15, Blogs Street, Durham, DH2 ABC, 0191 123 4567, 07001212111, patrick&sheila#madeupemail.com, SMS
Quite new to this so any help would be amazing
The correct code would be the following:
echo
"<div class='film'>
<span class='filmID'>5</span>
<span class='title'>my darling clementine</span>
<span class='category'>epic</span>
<span class='notes'>Henry Fonda</span>
</div>";
As the first double quote starts the string and the next closes the string.
SO "<div class="film"> is erroneous.
Or you may as well escape the double quote on the inside:
echo
"<div class=\"film\">
<span class=\"filmID\">5</span>
<span class=\"title\">my darling clementine</span>
<span class=\"category\">epic</span>
<span class=\"notes\">Henry Fonda</span>
</div>";
You are using double quotation inside string literal. It will confuse the parser. Use single quotation instead:
echo
"<div class='film'>
<span class='filmID'>5</span>
<span class='title'>my darling clementine</span>
<span class='category'>epic</span>
<span class='notes'>Henry Fonda</span>
</div>";
Try a heredoc
echo <<<HERE
<div class="film">
<span class="filmID">$filmID</span>
<span class="title">$filmTitle/span>
<span class="category">$filmCat</span>
<span class="notes">$filmNotes</span>
</div>
HERE;
Assuming that you want to use the variables you got from the DB, I think this is what you want. This answer also assume there is no PHP above this HTML. If there is you would have to leave PHP parsing (?>) before these lines.
<div class="film">
<span class="filmID"><?php echo $filmID; ?></span>
<span class="title"><?php echo $filmTitle; ?> </span>
<span class="category"><?php echo $filmCat; ?></span>
<span class="notes"><?php echo $filmNotes; ?></span>
</div>
<?php
//resume PHP parsing (if needed)

Php simple html dom parser find string with any character

I have this html
<div class="price-box">
<p class="old-price">
<span class="price-label">This:</span>
<span class="price" id="old-price-326">
8,69 € </span>
</p>
<p class="special-price">
<span class="price-label">This is:</span>
<span class="price" id="product-price-326">
1,99 € </span> <span style="">/ 6.87 </span>
</p>
</div>
I'm need get "1,99 €", but the id 'product-price-326' is generating random numbers. How to find 'product-price-*'? I'm trying
foreach($preke->find('span[id="product-price-[0-9]"]') as $div)
and
foreach($preke->find('span[id="product-price-"]') as $div)
but it doesn't work.
As per my comment, here's what you need to do:
foreach($preke->find('span[id^="product-price-"]') as $div) {} // note the ^ before the =
^= means starts with.
I am not sure what $preke is, but if it's a DOM selector that supports proper class selectors you can use
$preke->find('span[id^="product-price"]')
or
$preke->find('span[id*="product-price"]')
The ^= tells it to look for elements that has an ID starting with "product-price" and the *= tells it to look for elements that has an ID that contains "product-price".
Try Like This Might Be Works
foreach($preke->find('span[id^="product-price-"]') as $div) { /* Code */ }
why not to get it using class?
echo $preke->find('.special-price', 0)->find('.price', 0)->plaintext;
this will get you 1,99 €

Store the values of nested DOMNodes in a PHP array

I have the following html structure:
<span class="1">
<span class="name">
</span>
<span class="books">
<span class="english">
</span>
<span class="english">
</span>
</span>
</span>
<span class="2">
<span class="name">
</span>
<span class="books">
<span class="english">
</span>
<span class="english">
</span>
</span>
</span>
...
I am using the following function to retrieve it:
$oDomObject = $oDomXpath->query("//span[number(#class)=number(#class)]");
How can I store the values in a PHP array keeping the nesting order?
foreach ($oDomObject as $oObject) {
..*SOMETHING*..
}
Thank you for your help!
You will want to build a recursive function that resembles the following.
WARNING: Not-tested and may require some tweaking. But this should put your head in the right place.
foreach ($oDomObject as $oObject) {
$myArray[] = getChildren($oObject);
}
function getChildren($nodeObj) {
retArray = array();
if($nodeObj->hasChildren()) {
$retArray[] = getChildren($nodeObj);
} else {
$retArray[] = $nodeObj->nodeValue;
}
return $retArray;
}
What it does: If it encounters a node without children, it appends the value to the array. If not, it appends an array of the children's values to the array. This occurs ad nauseam, and as deeply as you can wrap your head around.
Things to think about:
What do I want my array to look like when this finishes, because with certain levels of depth, this gets very ridiculous and very annoying to traverse.
Why am I appending to an array, which I am likely to loop through again, instead of handling the desired operation right now?

php preg_replace the last link of two

I have many links out of one foreach. each foreach output some dom tree like:
<span id="span1">
<a(.*?)/test/(.*?)>word1</a>
</span>
<span id="span2">
<a(.*?)/fold/(.*?)>word2</a>
</span>
Now I want to replace the last link of the two, change the whole code as:
<span id="span1">
<a(.*?)/test/(.*?)>word1</a><!-- remain this link, do not replace. -->
</span>
<span id="span2">
word2
</span>
My preg_replace code here:
$code = '<span>test1</span><span>test2</span>';
echo preg_replace('%href="(.*?)/fold/(.*?)"%', 'href="#" class="replaced" title="$2"', $code);
I want get code like
<span id="span1">
test1
</span>
<span id="span2">
test2
</span>
But it will output <span id="span1">word2</span>, not as I expected. how to do well? thanks.
this will work (fixed):
preg_replace('(href="(.*?)/fold/(.*?)">(.*?)</a>)', 'href="#" class="replaced" title="$3">$3</a>', $code);
Thanks for onatm suggestion, finnally, I use simple_html_dom make a judge and get the code what I need.
$code = <<<EOT
<span id="span1">word1</span><span id="span2">word2</span>
EOT;
$html = str_get_html($code);
if($html->find("span[id=span1]")) {
foreach($html->find("span[id=span1]") as $data1)
$result1 = $data1;
}
if($html->find("span[id=span2]")) {
foreach($html->find("span[id=span2]") as $data2)
$result2 = preg_replace('%href="(.*?)/fold/(.*?)">(.*?)</a>%', 'href="#" class="replaced" title="$3">$3</a>', $data2);
}
echo $result1.''.$result2;

Categories