views:

328

answers:

2

Hello,

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. and html'>). That means HTML tag should be intact. But starting 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

A: 

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+>)?~'
Mikulas Dite
Actually I do not care about HTML. I care about the tags. Tags start with `<` and end with `>`. That will be enough. And Any solution other than regex is okay. I will try your answer. Thank you for your time :)
Sadi
Oh! do not forget about the length of each new string. It is the most important part
Sadi
+1  A: 

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"
}
oedo
Sorry! I forget to mention that. I am going to update the point.
Sadi
It looks like your solution discard the fullstops :P It would not be problem to add the full stops (I think) :)
Sadi
yeah just add a . to the end of each part :)
oedo
Hi would you please add the constraint: 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 :(
Sadi
i don't know what you mean, sorry. this is starting to sound very complicated, and you should be able to modify my code to do that yourself. after all, it's got all the elements you should need to do it.
oedo
That's okay! Thank you for help :)
Sadi