[Regex] &lt; en &gt; vervangen door < en >

Pagina: 1
Acties:
  • 157 views sinds 30-01-2008
  • Reageer

  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 21-02 21:06
In een grote lap tekst heb ik een aantal tags zitten die gecodeerd staan als & lt; en & gt; Deze wil ik vervangen door < > zodat het weer gewone HTML tags worden. Echter, moet dat natuurlijk alleen gebeuren wanneer het echt om tags gaat, dus in de vorm:
<a> b </a>
of
<a/>

Dit moet te doen zijn met een regex, ik zit alleen een beetje met het escapen en groeperen wat niet wil lukken.

Ik had zelf iets in de vorm van:
PHP:
1
preg_replace('/\& lt\;(.*)\& gt\; (.*) \& lt\;(.*)\/\& gt\;/si','<\\1>\\2</\\3>',$xmlcontent);


Maar die uitwerking doet het uiteraard niet, hopelijk begrijpt u allen wel wat ik bedoe zo.

De extra spaties zijn om te voorkomen dat hier ook < en > staat!!!!

[ Voor 31% gewijzigd door jsiegmund op 04-05-2006 13:31 ]


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Een tagopen kenmerkt zich in HTML door een < gevolgd door een letter [a-z] gevolgd door nul of meerdere name-karakters. Bij de tagclose komt daar nog een / bij uiteraard. De > hoeft strict genomen niet aanwezig te zijn, een tag kan je ook afsluiten mbv / of door een nieuwe tag te beginnen:
HTML:
1
<p<b/valid html/

Een unencoded < of > in content hoeft geen probleem te zijn, zolang het maar niet als tag aangemerkt kan worden. Scannen op <(.*?)> garandeerd je dus niet dat iets daadwerkelijk een tag is!
Verder hebben ook niet alle elementen in HTML een closetag; voor veel elementen is die optional en voor een aantal zelfs verboden.

Persoonlijk zou ik gewoon dit doen:
PHP:
1
$xmlcontent = str_replace(array('<', '>'), array('<', '>'), $xmlcontent);

Als dat al fout gaat dan was de content al ambigious om mee te beginnen.

[ Voor 15% gewijzigd door crisp op 04-05-2006 14:20 ]

Intentionally left blank


  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 21-02 21:06
Ik moet mezelf even verduidelijken denk ik ;)

De content wordt omgezet naar een XML structuur. Daar zit dus meteen het probleem, want een niet afgesloten tag mag daarin niet. Een losse < wordt ook herkend als tag dus gaat de content daarop de mist in. Daarom mag er echt alleen vervangen worden wanneer de tags gewoon volgens regels zijn. De korte versies kan ik daarbij geheel buiten beschouwing laten, want het gaat hier alleen om <B>, <I>, <P> en misschien een enkele hyperlink <A>.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

XML is inderdaad wat stricter, maar ik zou daar geen reguliere expressies voor gebruiken want de kans op malformed XML is vrij groot, denk bijvoorbeeld aan verkeerde nesting:
code:
1
<b><i>tralala</b></i>

dat soort dingen haal je er met een reguliere expressie niet uit.

Ik snap overigens nog steeds niet wat nou precies de bedoeling is; in je startpost heb je het over HTML en nu over XML. Kan je niet gewoon de content in een CDATA-sectie zetten?

Intentionally left blank


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Nog eens naar gekeken, dit lijkt goed te werken (maar is zeker niet voor de faint-of-heart ;) ):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//$xmlcontent = 'Dit is een <i>test met <b>goede</b> nesting</i> en 3 < 5';
$xmlcontent = 'Dit is een <i>test met <b>foute</i> nesting</b> en 3 < 5';

$xmlcontent = xml_callback($xmlcontent);

echo $xmlcontent;

function xml_callback($matches)
{
    $reg = '/<(i|b|p|a)(\s([^&]|&(?!gt;))*)?>((([^&]|&(?!lt;\/?\1>))*|(?R))*)<\/\1>/i';

    //-- recursive
    if (!is_array($matches))
        return preg_replace_callback($reg, 'xml_callback', $matches);
    else
        return '<' . $matches[1] . $matches[2] . '>' . preg_replace_callback($reg, 'xml_callback', $matches[4]) . '</' . $matches[1] . '>';
}

[ Voor 27% gewijzigd door crisp op 04-05-2006 17:04 ]

Intentionally left blank


Verwijderd

Ziek!
Die $reg is voor normale burgers zo goed als niet leesbaar.

Maar als 't werkt, petje af crisp! :)

kun je ook uitleggen wat 'ie doet?

  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 21-02 21:06
Mwa hij is nog wel leesbaar, maar ik krijg 'm niet aangepast ;)

Probleempje is namelijk: img en A tags mogen ook, en daar zitten dus nog x attributen in die ook mogen. Die hoeven verder niet gecontroleerd te worden, ik ga er even vanuit dat dat gewoon goed zit; krijg er toch geen syntax fouten door.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

iCe01 schreef op maandag 08 mei 2006 @ 15:39:
Mwa hij is nog wel leesbaar, maar ik krijg 'm niet aangepast ;)

Probleempje is namelijk: img en A tags mogen ook, en daar zitten dus nog x attributen in die ook mogen. Die hoeven verder niet gecontroleerd te worden, ik ga er even vanuit dat dat gewoon goed zit; krijg er toch geen syntax fouten door.
a-tags doet 'ie al, img-tags is een ander verhaal; die hebben natuurlijk geen closing-tag en vergen dus een andere approach (nesting is daar ook niet van belang)

Intentionally left blank


  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 21-02 21:06
Hmmm, dus een enkele br werkt ook niet? :) Ik ga wel even puzzelen, dit moet sowieso handiger / netter kunnen.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

iCe01 schreef op maandag 08 mei 2006 @ 16:19:
Hmmm, dus een enkele br werkt ook niet? :) Ik ga wel even puzzelen, dit moet sowieso handiger / netter kunnen.
Die elementen kan je gewoon met een simpele regexp afvangen; zoals gezegd kunnen die nooit voor nesting-errors zorgen; het enige dat je ws moet doen is XML-style short-closing toepassen:
<br> --> <br />
<img src="foo.gif"< --> <img src="foo.gif" />

lijkt me niet zo heel erg moeilijk om dat los van de afhandeling van elementen die wel een closing-tag hebben te doen.

Intentionally left blank


  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 21-02 21:06
Nope je hebt gelijk, ik dacht (te moeilijk) aan een enkele regex, maar hiervoor kan ik net zo goed een tweede maken, dat lukt me zelf ook nog wel. Thanks!

  • ZroBioNe
  • Registratie: Augustus 2001
  • Niet online
crisp schreef op maandag 08 mei 2006 @ 16:32:
[...]
<img src="foo.gif"< --> [img]"foo.gif"[/img][/nohtml]
<img src="foo.gif"< :? ;)

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 23-12-2025
crisp schreef op donderdag 04 mei 2006 @ 14:50:
Ik snap overigens nog steeds niet wat nou precies de bedoeling is; in je startpost heb je het over HTML en nu over XML. Kan je niet gewoon de content in een CDATA-sectie zetten?
Ander oplossing is:
PHP:
1
2
3
$doc = DomDocument::loadHTML($html);
$xml = $doc->saveXML();
// Niet getest, maar ik ga er stiekem vanuit dat het werkt.

  • jsiegmund
  • Registratie: Januari 2002
  • Laatst online: 21-02 21:06
De uiteindelijke oplossing was aanpakken van het probleem... door een goeie wysiwyg javascript editor te gebruiken weet ik nu zeker dat de input naar iso encoding wordt omgezet en er geen rare entities meer inzitten. Dan hoef je helemaal niks te controleren of om te zetten en kun je vervolgens alles prima als XML importeren. Soms zoek je aan de verkeerde kant naar de oplossing :)
Pagina: 1