Voor een hobby-projectje ben ik bezig met een xhtml-validator (in PHP), en een belangrijk onderdeel hiervan zijn enkele regular expressions. Ik wilde per se regexp's die niet mis kunnen gaan, maar die echt overal mee rekening houden.
Ik laad de complete source van een (x)html pagina in een string, en maak hiervan een array, door preg_split() hierop toe te passen, met de PREG_SPLIT_DELIM_CAPTURE optie, zodat ook de tags in de array komen.
Stap 1 was het herkennen van xhtml-tags, de elementen zonder attributes waren natuurlijk eenvoudig te vinden. Maar toen kwamen dus die attributes. Bij xhtml moeten de values tussen dubbele quotes staan, maar een value kan ook (geëscapete) quotes bevatten. Hierdoor zou voor dat stukje het patroon /"[^"]*"/ niet voldoende zijn.
Ik concentreerde me op dat probleem met backslashes, en kwam na een hoop geprobeerd te hebben op het volgende:
Eenvoudig gezegd: zoek bij het vinden van een dubbele quote " naar de eerstvolgende dubbele quote, die na 0 of een even aantal backslashes moet staan. Maar ik zie liever een andere optie dan de greed veranderen. Als ik dit namelijk toepas in een grotere regular expression, gaat het daardoor alsnog niet goed.
Dit is de regexp die ik nu heb voor een xhtml-start-tag:
Iets als <element attribute="tekst\\"nogmeertekst"> matcht, maar dat wil ik helemaal niet. Daarom moet die regular expression op één of andere manier anders. Ik wil dus niet dat die mbv. greed de korste gequote string zoekt, ik wil eigenlijk dat er geen even aantal backslashes, gevolgd door een dubbele quote in de string mág voorkomen.
Ik heb nu al vele dingen geprobeerd, teveel op op te noemen, maar ik kom er niet uit. Ik heb niet in de manual kunnen vinden hoe je zoekt naar de langst mogelijke string, waarin een bepaald patroon niet mag woorkomen.
Is er iemand die hier een oplossing voor weet?
Ik laad de complete source van een (x)html pagina in een string, en maak hiervan een array, door preg_split() hierop toe te passen, met de PREG_SPLIT_DELIM_CAPTURE optie, zodat ook de tags in de array komen.
Stap 1 was het herkennen van xhtml-tags, de elementen zonder attributes waren natuurlijk eenvoudig te vinden. Maar toen kwamen dus die attributes. Bij xhtml moeten de values tussen dubbele quotes staan, maar een value kan ook (geëscapete) quotes bevatten. Hierdoor zou voor dat stukje het patroon /"[^"]*"/ niet voldoende zijn.
Ik concentreerde me op dat probleem met backslashes, en kwam na een hoop geprobeerd te hebben op het volgende:
code:
1
| ".*?(?<!\\\\)(?:\\\\{2})*" |
Eenvoudig gezegd: zoek bij het vinden van een dubbele quote " naar de eerstvolgende dubbele quote, die na 0 of een even aantal backslashes moet staan. Maar ik zie liever een andere optie dan de greed veranderen. Als ik dit namelijk toepas in een grotere regular expression, gaat het daardoor alsnog niet goed.
Dit is de regexp die ik nu heb voor een xhtml-start-tag:
code:
1
| /(<[a-z]+(?:\s+[a-z\-]+=".*?(?<!\\\\)(?:\\\\{2})*")*\s*>)/i |
Iets als <element attribute="tekst\\"nogmeertekst"> matcht, maar dat wil ik helemaal niet. Daarom moet die regular expression op één of andere manier anders. Ik wil dus niet dat die mbv. greed de korste gequote string zoekt, ik wil eigenlijk dat er geen even aantal backslashes, gevolgd door een dubbele quote in de string mág voorkomen.
Ik heb nu al vele dingen geprobeerd, teveel op op te noemen, maar ik kom er niet uit. Ik heb niet in de manual kunnen vinden hoe je zoekt naar de langst mogelijke string, waarin een bepaald patroon niet mag woorkomen.
Is er iemand die hier een oplossing voor weet?