Split string into smaller part with constrain [PHP RegEx HTML]
I need to split long string into a array with following constrains:
- The input will be HTML string, may be full page or partial.
- Each part (new strings) will have a limited number of character (e.g. not more than 8000 character)
- Each part can contain multiple sentences (delimited by . [full stop]) but never a partial sentences. Except if the last part of the string (as last part may not have any full stop.
- The string contain HTML tags. But the tag can not be divided as (
<a href='test.html'>
to<a href='test
. andhtml'>
). That means HTML tag should be intact. But s开发者_如何学JAVAtarting tag and ending tag can be stay on different segment/chunk. - If any middle sentence is greater than the desired length, then leading and trailing tags and white spaces should be in different part of the array. Even after do so, if the sentence is longer, then divide it into multiple element of the array :(
- Please note that: No need to parse the HTML but tags (like or etc) <.*>
I think regular expression with preg_split can do it. Would please help me with the proper RegEx. Any solution other than regex also welcome.
Thank you
Sadi
correct me if i'm wrong, but i don't think you can do this with a simple regexp. in a full regexp implementation you could use something like this :
$parts = preg_split("/(?<!<[^>]*)\./", $input);
but php does not allow non-fixed-length lookbehind, so that won't work. apparently the only 2 that do are jgsoft and the .net regexp. Useful Page
my method of dealing with this would be :
function splitStringUp($input, $maxlen) {
$parts = explode(".", $input);
$i = 0;
while ($i < count($parts)) {
if (preg_match("/<[^>]*$/", $parts[$i])) {
array_splice($parts, $i, 2, $parts[$i] . "." . $parts[$i+1]);
} else {
if ($i < (count($parts) - 1) && strlen($parts[$i] . "." . $parts[$i+1]) < $maxlen) {
array_splice($parts, $i, 2, $parts[$i] . "." . $parts[$i+1]);
} else {
$i++;
}
}
}
return $parts;
}
you didn't mention what you want to happen when an individual sentence is >8000 chars long, so this just leaves them intact.
sample output :
splitStringUp("this is a sentence. this is another sentence. this is an html <a href=\"a.b.c\">tag. and the closing tag</a>. hooray", 8000);
array(1) {
[0]=> string(114) "this is a sentence. this is another sentence. this is an html <a href="a.b.c">tag. and the closing tag</a>. hooray"
}
splitStringUp("this is a sentence. this is another sentence. this is an html <a href=\"a.b.c\">tag. and the closing tag</a>. hooray", 80);
array(2) {
[0]=> string(81) "this is a sentence. this is another sentence. this is an html <a href="a.b.c">tag"
[1]=> string(32) " and the closing tag</a>. hooray"
}
splitStringUp("this is a sentence. this is another sentence. this is an html <a href=\"a.b.c\">tag. and the closing tag</a>. hooray", 40);
array(4) {
[0]=> string(18) "this is a sentence"
[1]=> string(25) " this is another sentence"
[2]=> string(36) " this is an html <a href="a.b.c">tag"
[3]=> string(32) " and the closing tag</a>. hooray"
}
splitStringUp("this is a sentence. this is another sentence. this is an html <a href=\"a.b.c\">tag. and the closing tag</a>. hooray", 0);
array(5) {
[0]=> string(18) "this is a sentence"
[1]=> string(25) " this is another sentence"
[2]=> string(36) " this is an html <a href="a.b.c">tag"
[3]=> string(24) " and the closing tag</a>"
[4]=> string(7) " hooray"
}
Unfortunately, html is irregular language, means you can't parse it with one regex. On the other hand, if the input is always similar, or you only need to parse some parts, it's not that problematic. Iteration over this regex generates elements name and it's content:
'~<(?P<element>\s+)(?P<attributes>[^>]*)>(?:(?P<content>.*?)</\s+>)?~'
精彩评论