[PHP] zoek n-th word probleem (maar dan ingewikkelder)

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 05-09 21:08
Mijn probleem:
  1. In mijn database staan textranges opgeslagen in de vorm: startwoordnummer.positie eindwoordnummer.positie. Dus het vette gedeelte in bijv.
    De snelle bruine vos
    geeft: 2.4 3.3, van woord 2 ('snelle'), positie 4 (na de 'l') naar woord 3 ('bruine'), positie 3 (na de 'u') . Hier kan ik niets aan doen - third-party etc.
  2. De tekst in de database is in HTML-formaat, bijv.
    HTML:
    1
    
    <p class="content">De snelle bruine <a href="www.vos.nl">vos</a></p>
  3. Wat ik wil: in de HTML een anchor (<a>) zetten achter het vette gedeelte uit de textrange bij puntje 1.
    HTML:
    1
    
    <p class="content">De snelle bru<a id="note1"></a>ine <a href="www.vos.nl">vos</a></p>
Hoe moet ik dit aanpakken? Ik kan het n-de woord in een string vinden (bijv. door te exploden op een spatie), maar in de HTML staan extra 'woorden': de tags. Als ik die weghaal, weet ik waar ik de anchor-string moet zetten in de platte tekst, maar nog niet in de HTML...

Acties:
  • 0 Henk 'm!

  • torx
  • Registratie: Oktober 2006
  • Laatst online: 19:40
Jij zoekt naar het volgende neem ik aan: http://nl.php.net/strip_tags ?

Edit > Oh wacht, ik lees je tekst nu wat beter.... Misschien dat je wat meer code kan geven? Op dit moment lijkt de oplossing zeer lastig, maar soms blijkt dat een andere methode beter is waardoor je het toch opgelost krijgt.

[ Voor 116% gewijzigd door torx op 24-09-2007 15:43 ]

Honda CB750 Hornet :: Yamaha Fazer FZ6 SA (2011 - 2023) | F1Pool.net


Acties:
  • 0 Henk 'm!

  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 05-09 21:08
Ik heb nog niet echt relevante code, omdat ik echt geen clue heb dit op te lossen. Die posities in de database (gerelateerd aan de platte tekst) en de tekst in HTML zijn mijn uitgangsposities, omdat die onderdeel vormen van een ander systeem.

Zelf zat ik te denken of ik e.e.a. niet met regular expressions (preg_match) kan oplossen.

PHP:
1
preg_match ( string $pattern, string $subject [, array &$matches [, int $flags [, int $offset]]] )


ik moet dan alle matches hebben van spaties buiten de tag-attributen zelf.

Dus de spatie tussen 'a' en 'h' in
HTML:
1
<a href="www.problems.nl">lastig probleem</a>
negeren, maar die tussen de 'g' en 'p' van 'lastig probleem' wel nemen.

Je kunt preg_match namelijk de offset van de matches laten teruggeven (mbv de flag PREG_OFFSET_CAPTURE).

Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 16:36
Je kunt preg_split gebruiken om eerst de tags er uit te filteren. Met de PREG_SPLIT_OFFSET_CAPTURE flag gezet krijg je de offsets erbij terug:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
//definieer een test string met een beetje HTML
$test = <<<TEST
      <h2>titel</h2>
      <p>En een introtekst
      <a href="#" class="more">&lt; tekst</a>
TEST;

//split de string op HTML tags
$plaintext = preg_split('/<[^>]+>/', $test, -1, PREG_SPLIT_OFFSET_CAPTURE);

//print het resulterende array
print_r($plaintext);

geeft
Array
(
    [0] => Array
        (
            [0] =>
            [1] => 0
        )
    [1] => Array
        (
            [0] => titel
            [1] => 7
        )
    [2] => Array
        (
            [0] =>
            [1] => 17
        )
    [3] => Array
        (
            [0] => En een introtekst
            [1] => 27
        )
    [4] => Array
        (
            [0] => &amp;gt; tekst
            [1] => 73
        )
    [5] => Array
        (
            [0] =>
            [1] => 87
        )
)


--EDIT--
Het resulterende array van arrays. Elk array bevat het platte deel van de tekst (zonder de HTML dus) en de start positie in de originele string. Entry [3], bevat bijvoorbeeld "En een introtekst", in de originele tekst begon dit stuk op positie 27.
Door spaties te tellen en in alle [0] entries van de arrays kun je uitvinden waar het n'de woord te vinden is. Met de positie van het deel in de originele tekst kun je de link op de juiste plaats zetten.

offtopic:
@therat10430: En als je verdere uitleg wil kun je daar ook gewoon om vragen, imho zijn het drie regels code die geen commentaar behoeven, nou ja, misschien wat de regex doet maar dat staat nu juist in de post voor de code...

[ Voor 30% gewijzigd door T-MOB op 24-09-2007 16:20 . Reden: commentaar / uitleg toegevoegd ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 19-09 10:19
Edit oops: drukte te vroeg ben nog aan het typen

ik denk dat je eerste de hele zin in een soort woord voor woord array moet zetten, (dit doe je door spaties te vinden, ik weet alleen de PHP syntax van mid$, len e.d. niet

dan krijg je:
De
snelle
bruine
vos

dan pak je woord 3: bruine, 3e positie.

daarna doe je len(woord1+spatie+woord2+spatie+3positiesvanwoord3) +1 dan heb je de eerste positie waar je anchor tag kan komen.

Ik denk dat het zo beredeneerd wel om te zetten is naar code.

@ T-mob, volgens mij is je code onnodig moeilijk/slecht(lees niet) voorzien van comments, ik snap er echt helemaal niks van 8)7

[ Voor 94% gewijzigd door roy-t op 24-09-2007 16:02 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 05-09 21:08
Bedankt T-MOB. Jouw oplossing lijkt te werken, alleen heb ik nog een probleem met speciale characters, zoals & l t ; (<). In Javascript - waarin de woord-referentie aangemaakt wordt - is dit een letter, maar jouw construct is het een woord. Maar goed, dit is ook weer af te vangen.

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Ikzelf zou voor een soort tokenizer (als dat de juiste term is) kiezen.
Loop door je tekst heen en tel de spaties.
Als je een "<" tegenkomt negeer je de spaties tot je de ">" tegen komt. Iets in de trant van;
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php 
$str = '<p class="content">De snelle bruine <a href="www.vos.nl">vos</a></p>'; 
$woord = 1; 
$letter = 0; 
$ignoring = false; 
for($i = 0; $i < strlen($str); $i++) { 
  $char = $str{$i}; 
  if($char == "<") { 
    $ignoring = true; 
  } elseif($char == ">") { 
    $ignoring = false; 
  } elseif($char == " " && !$ignoring) { 
    $woord++; 
    $letter = 0; 
  } elseif(!$ignoring) { 
    $letter++; 
    echo "'$char' is karakter {$letter} in woord {$woord} op positie $i in \$str\r\n"; 
  } 
} 
?>
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'D' is karakter 1 in woord 1 op positie 19 in $str
'e' is karakter 2 in woord 1 op positie 20 in $str
's' is karakter 1 in woord 2 op positie 22 in $str
'n' is karakter 2 in woord 2 op positie 23 in $str
'e' is karakter 3 in woord 2 op positie 24 in $str
'l' is karakter 4 in woord 2 op positie 25 in $str
'l' is karakter 5 in woord 2 op positie 26 in $str
'e' is karakter 6 in woord 2 op positie 27 in $str
'b' is karakter 1 in woord 3 op positie 29 in $str
'r' is karakter 2 in woord 3 op positie 30 in $str
'u' is karakter 3 in woord 3 op positie 31 in $str
'i' is karakter 4 in woord 3 op positie 32 in $str
'n' is karakter 5 in woord 3 op positie 33 in $str
'e' is karakter 6 in woord 3 op positie 34 in $str
'v' is karakter 1 in woord 4 op positie 57 in $str
'o' is karakter 2 in woord 4 op positie 58 in $str
's' is karakter 3 in woord 4 op positie 59 in $str


HTML-entiteiten zoals "&lt;" zou je terug kunnen converteren naar hun gelijkwaardige karakters met html_entity_decode(), alleen moet je een geconverteerde < dan niet gaan zien als opening van een HTML tag.
In bovenstaande zou je zoiets kunnen afvangen door ook te ignoren vanaf "&" tot en met ";".

[ Voor 71% gewijzigd door frickY op 25-09-2007 16:09 ]

Pagina: 1