[PHP] Whitespace strippen van html output

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik wil de output van mijn CMS'je graag versturen zonder breaks. Met andere woorden:
HTML:
1
2
3
4
5
6
7
<div id="mijn_div">
  <h1>Een kop</h1>
  <p>Hier de content</p>
</div>

/* wordt verstuurd als: */
<div id="mijn_div"><h1>Een kop</h1><p>Hier de content</p></div>

Ik heb hier (na een hoop gepruts) de volgende regex voor gevonden:
PHP:
1
$output = preg_replace("'([\r\n])[\s]+'", "", $output);

Dit werkt goed, behalve als er een textarea met content in de output zit:
HTML:
1
2
3
4
5
6
7
8
9
10
11
<div id="mijn_div">
  <textarea>
    * {
        margin: 0;
        padding: 0;
    }
  </textarea>
</div>

/* wordt nu verstuurd als: */
<div id="mijn_div"><textarea>* {margin: 0; padding: 0;}</textarea></div>

En dat moet dus niet. Als ik bv. een stylesheet open vanaf de server, ziet dat er niet uit in de textarea waarin je het kunt bewerken:
Cascading Stylesheet:
1
2
{margin: 0;padding: 0;}body {background: #fff url(bg.gif) repeat-x fixed;font: 75%/1.4 Arial, sans-serif;line-height: 18px;overflow: -moz-scrollbars-vertical;height: 100%;padding-top: 10px;}table, th, td {border-color: #9C9A9C; border-collapse: collapse;}img {border: 0;}img.icon {margin: 0 15px 16px 0; padding: 0 0 20px 0; vertical-align: top; float: 
/* etc. dus... */

Mijn vraag is dus hoe ik de regex moet aanpassen, zodat deze content tussen <textarea>-tags (en <pre> en <blockquote>-tags) ongemoeid laat. Welke regex koning kan mij helpen?

Acties:
  • 0 Henk 'm!

  • Springuin
  • Registratie: Juli 2002
  • Laatst online: 11-09 20:13
Ik ben geen held met regexpen en zou zelf een parser schrijven. Let wel op dat ie niet de mist in gaat als er in je textarea perongeluk een </textarea> staat.

Acties:
  • 0 Henk 'm!

Verwijderd

Dit kan eigenlijk alleen goed met een context-aware parser. Inlezen met een HTML parser, lege textNodes strippen, en dan weer serializen werkt waarschijnlijk het best.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Springuin schreef op dinsdag 30 september 2008 @ 19:48:
Ik ben geen held met regexpen en zou zelf een parser schrijven. Let wel op dat ie niet de mist in gaat als er in je textarea perongeluk een </textarea> staat
Verwijderd schreef op dinsdag 30 september 2008 @ 19:53:
Dit kan eigenlijk alleen goed met een context-aware parser. Inlezen met een HTML parser, lege textNodes strippen, en dan weer serializen werkt waarschijnlijk het best.
Jeetje, dat is mij wel wat boven mijn pet. Ik wil er best induiken, maar dacht zelf dat een oplossing met een regex ook zou kunnen, bijvoorbeeld:
PHP:
1
$output = preg_replace_callback("/>[^<]*<\\/textarea/", "do_stuff", $output);

De functie do_stuff zou dan de linebrakes en multiple spaces in de textarea moeten bewaken, oid...iemand hier ideeen over?

Acties:
  • 0 Henk 'm!

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 20-09 00:06
Je kan beter mod_gzip oid gebruiken als je doel is om je HTTP body qua grootte in te perken, want een goede parser voor je HTML output schrijven die whitespace op de juiste plek intact laat is niet triviaal (omdat HTML niet zo simpel is als well-formed XML) en zal zeker trager zijn.

Acties:
  • 0 Henk 'm!

  • Cousin Boneless
  • Registratie: Juni 2008
  • Laatst online: 28-02 12:55
PHP:
1
2
3
4
5
6
7
8
9
10
$array = preg_split('%(<(textarea|pre|blockquote)>[\s\S]*?</\2>)%i', $text, -1, PREG_SPLIT_DELIM_CAPTURE);

$result = '';
for ($i=0; $i<count($array); $i+=3)
{
    $result .= preg_replace('%([\s]*[\r\n][\s]*)%', '', $array[$i]);
    $result .= $array[$i+1];
}

echo $result;

Misschien heb je er wat aan..

[ Voor 9% gewijzigd door Cousin Boneless op 01-10-2008 01:25 . Reden: nu ook met <pre> en <blockquote> ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

<textarea> is 1, <pre> is nog een ander waar je rekening moet houding met het preserveren van whitespace

Intentionally left blank


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Cousin Boneless schreef op woensdag 01 oktober 2008 @ 00:59:
PHP:
1
2
3
4
5
6
7
8
9
10
$array = preg_split('%(<(textarea|pre|blockquote)>[\s\S]*?</\2>)%i', $text, -1, PREG_SPLIT_DELIM_CAPTURE);

$result = '';
for ($i=0; $i<count($array); $i+=3)
{
    $result .= preg_replace('%([\s]*[\r\n][\s]*)%', '', $array[$i]);
    $result .= $array[$i+1];
}

echo $result;

Misschien heb je er wat aan..
Dank je wel, maar hiermee worden ook de newlines in een textarea gestript. Weet iemand waarom?

Acties:
  • 0 Henk 'm!

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Waarom wil je dit doen? Om je dataverkeer binnen de perken te houden? Gebruik dan mod_gzip of mod_deflate of een IIs variant, maar ga niet zo klooien. Code obfuscaten? Met een code formatter zie ik het zo weer netjes voor me, en met Firebug kan ik prima je hele DOM doorlopen. Eerlijk gezegd mis ik dus een beetje het nut hiervan.

[ Voor 8% gewijzigd door AtleX op 01-10-2008 08:17 ]

Sole survivor of the Chicxulub asteroid impact.


Acties:
  • 0 Henk 'm!

  • dik_voormekaar
  • Registratie: April 2003
  • Laatst online: 15-09 21:32
crisp schreef op woensdag 01 oktober 2008 @ 01:03:
<textarea> is 1, <pre> is nog een ander waar je rekening moet houding met het preserveren van whitespace
<script> ... </script> is er nog zo een.

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Voor script in principe niet hoor. Als jij je aanwent elke statement netjes af te sluiten met een semicolon, kan je complete classes op 1 regel kloppen.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

MueR schreef op woensdag 01 oktober 2008 @ 08:32:
Voor script in principe niet hoor. Als jij je aanwent elke statement netjes af te sluiten met een semicolon, kan je complete classes op 1 regel kloppen.
Feit is dat de semicolon in javascript niet verplicht is en vaker weggelaten wordt dan je denkt ;)

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Dan nog maakt Atlex een goed punt. Als ts nog niets met gzip of iets dergelijks doet kan hij wellicht eerst beter daar naar kijken.

{signature}


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 16:36
En dan is er ook nog:
Cascading Stylesheet:
1
white-space: pre;


* T-MOB raadt ook mod-gzip aan...

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
crisp schreef op woensdag 01 oktober 2008 @ 11:50:
[...]

Feit is dat de semicolon in javascript niet verplicht is en vaker weggelaten wordt dan je denkt ;)
Dat hangt redelijk af van de context. In statements als while(foo != bar++); is de semicolon verplicht, net als na return, break, continue en do-while bijvoorbeeld. De exacte regels voor Automatic Semicolon Insertion (zoals dat in de EMCA standaard zo mooi heet) weet ik niet uit m'n hoofd.

Verder als de whitespace er perse uit moet kun je de DOM traversen en de nodes die alleen uit whitespace bestaan verwijderen. Daarna kun je (eventueel) context aware nog de nodes die niet pre, textarea, style="white-space: pre" et cetera hebben strippen. Punt is dat dat een vrij foutgevoelig proces is.

Acties:
  • 0 Henk 'm!

  • samo
  • Registratie: Juni 2003
  • Laatst online: 12:46

samo

yo/wassup

In PHP5 is Tidy geloof ik makkelijk benaderbaar. Die heeft ook een optie voor whitespaces trimmen. php.net.

Bekend van cmns.nl | ArneCoomans.nl | Het kindertehuis van mijn pa in Ghana


Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online

Guillome

test

Een vluchtige gedachte:
Alle linebreaks binnen een textarea vervangen door een unieke code (##ENTER## ofzo)
Daarna alle linebreaks verwijderen (\n\r dus)
Daarna alle ##ENTER## vervangen door linebreak.

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online

Guillome

test

PrisonerOfPain schreef op woensdag 01 oktober 2008 @ 12:54:
[...]


Dat hangt redelijk af van de context. In statements als while(foo != bar++); is de semicolon verplicht
Is dat zo??

code:
1
2
3
while (tmp = get_next())
{
}

Is toch juist?

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

PrisonerOfPain schreef op woensdag 01 oktober 2008 @ 12:54:
[...]


Dat hangt redelijk af van de context. In statements als while(foo != bar++); is de semicolon verplicht, net als na return, break, continue en do-while bijvoorbeeld. De exacte regels voor Automatic Semicolon Insertion (zoals dat in de EMCA standaard zo mooi heet) weet ik niet uit m'n hoofd.
De semi-colon is daar in zoverre verplicht dat het anders iets anders doet dan wat je voor ogen had ;)

Ik bedoelde te zeggen dat veel mensen toch semi-colons weglaten na bepaalde statements en declaraties waar je 'm eigenlijk wel zou moeten plaatsen wil je successvol whitespace kunnen strippen. Guillomme geeft hierboven al een voorbeeld, een ander voorbeeld is een functie declaratie:
JavaScript:
1
2
3
4
function foo()
{
  return 'bar';
}; // <-- belangrijk!

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarom is die belangrijk? Dit werkt gewoon:
JavaScript:
1
function foo() { } function bar() { }


't Wordt natuurlijk wat anders als je zegt
JavaScript:
1
2
3
foo = function()
{
}; // <-- nu wel belangrijk!

[ Voor 36% gewijzigd door .oisyn op 01-10-2008 13:54 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Snake
  • Registratie: Juli 2005
  • Laatst online: 07-03-2024

Snake

Los Angeles, CA, USA

JavaScript:
1
2
3
4
5
        function blah()
{
    alert("eerste")
    alert("tweede")
}


Dit zal ook niet werken op 1 regel

Going for adventure, lots of sun and a convertible! | GMT-8


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hence crisp in "[PHP] Whitespace strippen van html output", wat de oorzaak was van deze hele subdiscussie ;)

[ Voor 22% gewijzigd door .oisyn op 01-10-2008 13:59 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Guillome schreef op woensdag 01 oktober 2008 @ 13:02:
[...]

Is dat zo??

code:
1
2
3
while (tmp = get_next())
{
}

Is toch juist?
Correct, wat ik bedoelde te zeggen was dat je daar dus geen whitespace kunt plaatsen als vervanging.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 15:29

crisp

Devver

Pixelated

.oisyn schreef op woensdag 01 oktober 2008 @ 13:51:
Waarom is die belangrijk? Dit werkt gewoon:
JavaScript:
1
function foo() { } function bar() { }


't Wordt natuurlijk wat anders als je zegt
JavaScript:
1
2
3
foo = function()
{
}; // <-- nu wel belangrijk!
d*mn, die bedoelde ik ook :P Zelfde geldt voor het gebruik van object literals e.d.:
JavaScript:
1
2
3
4
var foo = {
  bla: 1,
  woei: 2
}; // <-- ook belangrijk

en natuurlijk single-line comments, daar wil je de enter daarna ook niet strippen (als je de comment zelf niet stript) :)

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Guillome schreef op woensdag 01 oktober 2008 @ 13:01:
Daarna alle linebreaks verwijderen (\n\r dus)
\r\n dus. :z

{signature}


Acties:
  • 0 Henk 'm!

  • Cousin Boneless
  • Registratie: Juni 2008
  • Laatst online: 28-02 12:55
Dank je wel, maar hiermee worden ook de newlines in een textarea gestript. Weet iemand waarom?
Als ik je voorbeeld er door haal, blijft de inhoud van de textarea intact. De oplossing werkt niet indien je attributen aan de textarea-tag toevoegt, maar dat is een minimale wijziging in de eerste regexp.

Ik idem trouwens iedereen die zegt dat dit maar een marginale oplossing biedt voor het inperken van je dataopslag. Ga eens na wat de verhouding is tussen de opslag van binaire data (jpegs etc) en dat van tekst.

Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online

Guillome

test

Wat maakt dat nou uit?
preg_replace("/[\n\r]/"...

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

't Maakt ook niet zoveel uit. Maar \r is de mac linebreak, \n is de *nix linebreak, en de \r\n combinatie is de windows linebreak (die tevens gehanteerd wordt door de meeste textuele protocollen zoals HTTP en FTP). \n\r is niets, jij bedoelt alle individuele \r's en \n's, vandaar waarschijnlijk de verwarring.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Snake schreef op woensdag 01 oktober 2008 @ 13:58:
JavaScript:
1
2
3
4
5
        function blah()
{
    alert("eerste")
    alert("tweede")
}


Dit zal ook niet werken op 1 regel
Daarom zeg ik ook dat je dit netjes moet doen. Overal waar het kan, doen. Dit is gewoon slordig programmeren.

[ Voor 5% gewijzigd door MueR op 01-10-2008 15:08 ]

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
offtopic:
Hier maakt het ook niets uit, ik stoor mij gewoon altijd erg aan deze 4e zelfverzonnen variant. Move along people. :P

{signature}


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

MueR schreef op woensdag 01 oktober 2008 @ 15:08:
[...]

Daarom zeg ik ook dat je dit netjes moet doen. Overal waar het kan, doen. Dit is gewoon slordig programmeren.
Onzin, er is niets slordigs aan. Het is pas slordig als je wel en geen puntkomma's om je statements af te sluiten door elkaar gaat gebruiken. Het punt is dat jij het slordig vindt omdat alle C-like dialecten de ; vereisen, maar dat is ook maar een conventie. Javascript deelt die conventie niet. Volgens jouw logica is programmeren in Basic ook slordig (ok, is wat voor te zeggen... Haskell dan ;)).

[ Voor 9% gewijzigd door .oisyn op 01-10-2008 16:19 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

Goed, ik zal nuanceren, je moet consequent programmeren :P

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Cousin Boneless schreef op woensdag 01 oktober 2008 @ 00:59:
PHP:
1
2
3
4
5
6
7
8
9
10
$array = preg_split('%(<(textarea|pre|blockquote)>[\s\S]*?</\2>)%i', $text, -1, PREG_SPLIT_DELIM_CAPTURE);

$result = '';
for ($i=0; $i<count($array); $i+=3)
{
    $result .= preg_replace('%([\s]*[\r\n][\s]*)%', '', $array[$i]);
    $result .= $array[$i+1];
}

echo $result;

Misschien heb je er wat aan..
Cousin Boneless schreef op woensdag 01 oktober 2008 @ 14:22:
[...]

Als ik je voorbeeld er door haal, blijft de inhoud van de textarea intact. De oplossing werkt niet indien je attributen aan de textarea-tag toevoegt, maar dat is een minimale wijziging in de eerste regexp.
Hoe zou ik die dan moeten wijzigen?

Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Gewoon alle karakters toestaan tussen de tagnaam en de sluittag.

Zoiets dus: <(textarea|pre|blockquote).*?>

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
BalusC schreef op woensdag 01 oktober 2008 @ 17:44:
Gewoon alle karakters toestaan tussen de tagnaam en de sluittag.

Zoiets dus: <(textarea|pre|blockquote).*?>
Dank je wel, zo te zien werkt het perfect. Ik probeer me in te denken wanneer de functie die ik nu heb, problemen zou kunnen opleveren. Ik ga eea uitproberen, maar als iemand al ideeen heeft, dan hoor ik dat graag :)

Acties:
  • 0 Henk 'm!

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Ik vraag me nog steeds af waarom je dit wilt doen?

Sole survivor of the Chicxulub asteroid impact.

Pagina: 1