Autor Zpráva
dunky
Profil
Upravuji stránky na kterých je redakční systém PhpRs. Vyskytla se nutnost exportovat články. Obrázky do článků se v tomto CMS vkládají pomocí speciálních tagů, které obsahují id obrázků v databázi a další informace. Např.
<obrazek id="8" zarovnani="vlevo" nahled="ano" velikost="90%" odkaz="http://www.volny.cz/ks.praha-sever/2004-11/_index.html"/>
Napadlo mě pomocí preg_replace_callback() vyhledat v každém článku všechny takové tagy. Vyextrahovat všechny informace v atributech. A poté na základě toho vytvořit normální html. Cíl je tedy něco takového:
<a href="http://www.volny.cz/ks.praha-sever/2004-11/_index.html"><img width="90%" style="float: left;"></a>

Je to lépe udělat pomocí více regulárních výrazů, nebo jednoho souhrného? Je jeden rychlejší než vícero?
Napadlo mě udělat to pomocí pojmenovaných subvýrazů (?P<jmeno_vyrazu>.*). Zatím jsem dospěl k tomuto. Ale nevím si rady s tím, kdyby byly atributy spřeházené.
'<obrazek[ ]+id=[\'"]?(?P<id>[\d]+)[\'"]?[ ]+zarovnani=[\'"]?(?P<zarovnani>[\w]+)[\'"]?(.*)>'

Asi bude potřeba minimálně dvou regulární výrazů.
Kcko
Profil
dunky:
Je to lepší udělat pomocí DOMu (zkus tuto knihovnu http://simplehtmldom.sourceforge.net/ )
dunky
Profil
Toho jsem si také vědom. Trénuju regulární výrazy, takže jsem si to neulehčil :)
Našel jsem regulární výraz, který najde všechny atributy a jejich hodnoty: (\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?
Ale znamená to upustit od původní ideji. Čistě mě zajímá, jestli něco takového technicky jde.
Tori
Profil
Pokud se můžete spolehnout na to, že hodnoty parametrů nebudou obsahovat mezeru, je možné použít i explode a rozsekat to nejdřív podle mezer, pak jednotlivé dílky ještě podle rovnítek. Anebo nahradit mezery ampersandem, vyhodit uvozovky a apostrofy a pomocí parse_str převést na pole.
Ten regulár ve [#3] vám funguje? Mně od každé hodnoty našel jen první znak. (neplatí, moje chyba)
Ten regulár bude mít problém v situaci, kdy se uvnitř hodnoty v uvozovkách ocitne apostrof - bude ho brát jako uzavírací uvozovku. Mně fungoval třeba takovýhle: ~(\S+)=(["'])(.+)(\\2)~U (kdy do funkce preg_match_all posílám už jen ty nalezené atributy s hodnotami, bez názvu tagu a ostrých závorek celý tag <obrazek>).

A jak je to řešené v tom phpRS - přece se taky nějak musí ten vlastní tag převádět na HTML, ne?

edit: upravila jsem regulár, aby se mu dal předhodit celý tag.
edit2: a takhle chytí i atributy bez uvozovek/apostrofů okolo hodnoty:
preg_match_all('~(\\S+)=(?:["\'])?(.+)(?:\\2)?(?=[\\s]|/?>)~U', $tag_nebo_atributy, $nalezene, PREG_SET_ORDER);
dunky
Profil
Tori:
Ten regulár ve [#3] jsem netestoval.
Jak je to udělané v tom PhpRs jsem radši nekoukal je to hrozná prasárna :D Ale možná to přece jen zjistím.
Edit:
Tak tam je to samé strpos , expolode a substr :D možná to je ve výsledku rychlejší než regulár, ale než abych se tím prokousával, radši jsem si řekl že se na tom ty regulární výrazy naučím...
peta
Profil
Našel jsem regulární výraz, který najde všechny atributy a jejich hodnoty: (\S+)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?
Si ten regularni vyraz rozeber, ne?

\S+ znak, ktery neni mezera 1-n krat
= rovnitko
["']? apostrof nebo uvozovka 0-1 krat
. jakykoliv znak
["']? apostrof nebo uvozovka 0-1 krat
\s+ mezera 1-n krat
\S+ znak, ktery neni mezera 1-n krat
= rovnitko
[>"'] konec tagu > nebo apostrov a nebo uvozovka
+ to cele opakuj aspon 1x
. - jakykoliv znak
["'] - apostrof

<aaa bbb="ccc"ddd="eee">
Z toho plyne, ze vyzaduje aspon jeden mezerovy znak jako oddelovac tak to zkape.
<aaa bbb=ccc ddd=eee>
Vyzaduje apostrof nebo uvozovku tak to opet zkape.
<aaa> bbb=ccc ddd=eee</aaa>
Chyti se to i na text uprostred.
<aaa> bbb="ccc'ddd'"</aaa>
Jak psala Tori, kdyz mas v uvozovkach apostrof, tak to najde ddd="ccc'.
<?php $$$="---" ###="!!!"?>
Tohle ti klidne uzna jako parametry.
<!--  bbb="ccc" ddd="eee" -->
A tohle take uzna jako parametry.

Mno, a to vsechno vidis z toho rozboru regularu. Ja jen, ze takovy vyraz neni zrovna jednoducha zalezitost a spis bych pouzil vestaveny parser simpleXML nebo jinou cestu.
Ja bych zustal u explode. Nebo pak uz callback s regularem, aby to bylo rychlejsi.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: