How Can I Display First 2 Paragraphs? And then Remaining Paragraphs? - PHP - php

I have 4 paragraphs of text in one string. Each paragraph is surrounded with <p></p>.
My first goal is to output the first 2 paragraphs.
My second goal it to output the remaining paragraphs somewhere else on the page. I could sometimes be dealing with strings containing more than 4 paragraphs.
I've searched on the web for anything already out there. There's quite a bit about displaying just the first paragraph, but nothing I could find about displaying paragraphs 1-2 and then the remaining paragraphs. Can anyone help here?
Not sure which to use if any, substr, strpos, etc.....?
EDIT - thanks for your answers, to clarify, the paragraphs don't contain HTML at the moment, but yes I will need the option to have HTML within each paragraph.

Use regular expression:
$str = '<p style="color:red;"><b>asd</b>para<img src="afs"/>graph 1</p >
<p>paragraph 2</p>
<p>paragraph 3</p>
<p>paragraph 4</p>
';
// preg_match_all('/<p.*>([^\<]+)<\/p\s*>/i',$str,$matches);
//for inside html like a comment sais:
preg_match_all('/<p[^\>]*>(.*)<\/p\s*>/i',$str,$matches);
print_r($matches);
prints:
Array
(
[0] => Array
(
[0] => <p style="color:red;"><b>asd</b>para<img src="afs"/>graph 1</p >
[1] => <p>paragraph 2</p>
[2] => <p>paragraph 3</p>
[3] => <p>paragraph 4</p>
)
[1] => Array
(
[0] => <b>asd</b>para<img src="afs"/>graph 1
[1] => paragraph 2
[2] => paragraph 3
[3] => paragraph 4
)
)

Use DOMDocument
Initialize with:
$dom = new DOMDocument;
$dom->loadHTML($myString);
$p = $dom->getElementsByTagName('p');
If each can contains other HTML elements(or not), create a function:
function getInner(DOMElement $node) {
$tmp = "";
foreach($node->childNodes as $c) {
$tmp .= $c->ownerDocument->saveXML($c);
}
return $tmp;
}
and then use that function when needing the paragraph like so:
$p1 = getInner($p->item(0));
You can read more about DOMDocument here

Related

Foreach does not get xpath results from node

I use xpath webdriver to find a div in the code and I need to get data on each node of this div, but this is not happening.
HTML:
<div class="elements">
<div class="element"><div class="title">Title A</div></div>
<div class="element"><div class="title">Title B</div></div>
<div class="element"><div class="title">Title C</div></div>
</div>
PHP Code:
$elements = array();
$data = $driver->findElements(WebDriverBy::xpath("//div[#class='elements']//div[#class='element']"));
foreach ($data as $i => $element) {
$elements[$i]["title"] = $element->findElement(WebDriverBy::xpath("//div[#class='title']"))->getText();
}
Result Array $elements being returned:
Array
(
[0] => Array
(
[title] => Title A
)
[1] => Array
(
[title] => Title A
)
[2] => Array
(
[title] => Title A
)
)
The above script is only returning Title A 3 times.
I need it to work like it has a numeral in xPath [x]. Exemple:
(//div[#class='elements']//div[#class='element'])[1]//div[#class='title'] for Title A
(//div[#class='elements']//div[#class='element'])[2]//div[#class='title'] for Title B
(//div[#class='elements']//div[#class='element'])[3]//div[#class='title'] for Title C
I can't use numeral because xPath is too big and would mess up the code a lot.
Surely the correct node xPath in foreach wasn't supposed to work?
When using WebElement to locate another WebElement with xpath you need to use current context . in the path
$element->findElement(WebDriverBy::xpath(".//div[#class='title']"))

Is it possible to exclude parts of the matched string in preg_match?

when writing a script that is supposed to download content from a specific div I was wondering if it is possible to skip some part of the pattern in such a way that it will not be included in the matching result.
examlple:
<?php
$html = '
<div class="items">
<div class="item-s-1827">
content 1
</div>
<div class="item-s-1827">
content 2
</div>
<div class="item-s-1827">
content 3
</div>
</div>
';
preg_match_all('/<div class=\"item-s-([0-9]*?)\">([^`]*?)<\/div>/', $html, $match);
print_r($match);
/*
Array
(
[0] => Array
(
[0] => <div class="item-s-1827">
content 1
</div>
[1] => <div class="item-s-1827">
content 2
</div>
[2] => <div class="item-s-1827">
content 3
</div>
)
[1] => Array
(
[0] => 1827
[1] => 1827
[2] => 1827
)
[2] => Array
(
[0] =>
content 1
[1] =>
content 2
[2] =>
content 3
) ) */
Is it possible to omit class=\"item-s-([0-9]*?)\" In such a way that the result is not displayed in the $match variable?
In general, you can assert strings precede or follow your search string with positive lookbehinds / positive lookaheads. In the case of a lookbehind, the pattern must be of a fixed length which stands in conflict with your requirements. But fortunately there's a powerful alternative to that: You can make use of \K (keep text out of regex), see http://php.net/manual/en/regexp.reference.escape.php:
\K can be used to reset the match start since PHP 5.2.4. For example, the patter foo\Kbar matches "foobar", but reports that it has matched "bar". The use of \K does not interfere with the setting of captured substrings. For example, when the pattern (foo)\Kbar matches "foobar", the first substring is still set to "foo".
So here's the regex (I made some additional changes to that), with \K and a positive lookahead:
preg_match_all('/<div class="item-s-[0-9]+">\s*\K[^<]*?(?=\s*<\/div>)/', $html, $match);
print_r($match);
prints
Array
(
[0] => Array
(
[0] => content 1
[1] => content 2
[2] => content 3
)
)
The preferred way to parse HTML in PHP is to use DomDocument to load the HTML and then DomXPath to search the result object.
Update
Modified based on comments to question so that <div> class names just have to begin with item-s-.
$html = '<div class="items">
<div class="item-s-1827">
content 1
</div>
<div class="item-s-18364">
content 2
</div>
<div class="item-s-1827">
content 3
</div>
</div>';
$doc = new DomDocument();
$doc->loadHTML($html);
$xpath = new DomXPath($doc);
$divs = $xpath->query("//div[starts-with(#class,'item-s-')]");
foreach ($divs as $div) {
$values[] = trim($div->nodeValue);
}
print_r($values);
Output:
Array (
[0] => content 1
[1] => content 2
[2] => content 3
)
Demo on 3v4l.org

Insert String from Array after X amount of characters (Outside HTML) in PHP

I've looked and can't find a solution to this feature we would like to write. I'm fairly new to PHP so any help, advice and code examples are always greatly appreciated.
Let me explain what we want to do...
We have a block of HTML inside a string - the content could be up to 2000 words with styling such as <p>, <ul>, <h2> included in this HTML content string.
We also have an array of images related to this content inside a separate string.
We need to add the images from the array string into the HTML content at equal spaces without breaking the HTML code. So a simple character count won't work as it could break the HTML tags.
We need to equally space the images. So, for example; if we had 2000 words inside the HTML content string and 10 images in the array, we need to place an image every 200 words.
Any help or coding samples provided in order to achieve this is greatly appreciated - thank you for your help in advance.
You can use
$numword = str_word_count($str, 0);
for getting the number of row
or
$array = str_word_count($str,1);
for getting in $array an array with all the word (one for index) and then iterating on this array for rebuild text you need adding every number of time (word) the code for your image
This Sample is form php Manual
<?php
$str = "Hello fri3nd, you're
looking good today!";
print_r(str_word_count($str, 1));
print_r(str_word_count($str, 2));
print_r(str_word_count($str, 1, 'àáãç3'));
echo str_word_count($str);
?>
this is related result
Array
(
[0] => Hello
[1] => fri
[2] => nd
[3] => you're
[4] => looking
[5] => good
[6] => today
)
Array
(
[0] => Hello
[6] => fri
[10] => nd
[14] => you're
[29] => looking
[46] => good
[51] => today
)
Array
(
[0] => Hello
[1] => fri3nd
[2] => you're
[3] => looking
[4] => good
[5] => today
)
7
You can find it in this doc
for the insert you can try this way
$num = 200; // number of word after which inert the image
$text = $array[0]; // initialize the text with the first word in array
for ($cnt =1; $cnt< count( $array); $cnt++){
$text .= $array[$cnt]; // adding the word to the text
if (($cnt % $num) == 0) { // if array index multiple fo 200 insert the image
$text .= "<img src='your_img_path' >";
}
}

PHP ARRAY_PUSH strips html tag

I have a string which i am trying to split and then add a span tag on every 2 words.
When I split the string and try to use array_push to create a new array, my html tags disappears.
Here is my function:
public function splitString(){
$string = Sample sentence;
$newHeader = array();
$parts = preg_split('/\s+/', $string);
$num = 1;
foreach($parts as $str){
if($num % 2 == 0){
array_push($newHeader, "<span>".$str."</span>");
}else{
array_push($newHeader, $str);
}
$num++;
}
return $newHeader;
}
When I call that function the result i get is
Array ( [0] => Sample [1] => sentence )
I am looking for:
Array ( [0] => Sample [1] => <span>sentence</span> )
What I am doing wrong? Please help
Thank you in advance
First, if you haven't corrected, just like #Fred said in the comments, you should quote your strings in that function:
$string = 'Sample sentence';
Second, it works. array_push() does not strip your tags. You are just presented with a print_r() on the browser but its there along with the word.
Array ( [0] => Sample [1] => sentence )
If look at it in the view source. This is what it looks like:
print_r(splitString());
Array
(
[0] => Sample
[1] => <span>sentence</span>
)
You just don't see it visually on the browser but the tags are there.
If you try to add this up:
array_push($newHeader, "<span style='color: red;'>".$str."</span>");
You'll see the style. Try it :)

Find h3 and h4 tags beneath it

This is my HTML:
<h3>test 1</h3>
<p>blah</p>
<h4>subheading 1</h4>
<p>blah</p>
<h4>subheading 2</h4>
<h3>test 2</h3>
<h4>subheading 3</h4>
<p>blah</p>
<h3>test 3</h3>
I am trying to build an array of the h3 tags, with the h4 tags nested within them. An example of the array would look like:
Array
(
[test1] => Array
(
[0] => subheading 1
[1] => subheading 2
)
[test 2] => Array
(
[0] => subheading 3
)
[test 3] => Array
(
)
)
Happy to use preg_match or DOMDocument, any ideas?
With DOMDocument:
use XPath "//h3" to find all <h3>. These will be the first-level entries in your array
for each of them:
count a variable $i (count from 1!) as part of the loop
use XPath "./following::h4[count(preceding::h3) = $i]" to find any sub-ordinate <h4>
these will be second-level in you array
The XPath expression is "select all <h4> that have a the same constant number of preceding <h3>". For the first <h3> that count is 1, naturally, for the second the count is 2, and so on.
Be sure to execute the XPath expression in the context of the respective <h3> nodes.

Categories