Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

yoda

desafio regex

Recommended Posts

yoda

Boas,

Estou aqui com um problema / nao-saber-como-fazer em relação ao uso de expressões regulares. Quero fazer parse de um ficheiro html e retirar o conteúdo de todas as divs que contenham a class editable, para poder posteriormente ser editadas num backoffice. Já consigo, e não foi difícil, sacar a informação das divs com essa classe :

preg_match_all('/<div[^>]*class="[^"]*(editable){1}[^"]*"[^>]*>(.*?)<\/div>/si', $this->xhtml, $parts, PREG_SET_ORDER);

Agora o problema : Este trecho de código funciona na perfeição para divs que contenham tudo lá dentro excepto outras divs, que é onde este regex falha. Preciso portanto que ele me saiba identificar divs dentro da que tem a class editable, ou seja, identificar inicios e fechos das mesmas, de modo a não colidir com a principal. Penso que seja possível com regex, mas daí a saber como o fazer ..  🤔

Alguém tem dicas?

Obrigado

Share this post


Link to post
Share on other sites
Nazgulled

Não percebi bem onde é que o teu código funciona e onde falha... Podes dar vários exemplos de teste onde não está a funcionar e gostavas que funcionasse?

E acho que és capaz de ter esse regex ligeiramente mais complexo do que precisas, mas é só o que me parece à primeira vista, posso estar errado.

Share this post


Link to post
Share on other sites
yoda

Boas,

Este regex apanha os seguintes exemplos :

<div (qualquer coisa por aqui) class=" (qualquer coisa por aqui) editable (qualquer coisa por aqui)" (qualquer coisa por aqui) "> (conteudo) </div>

O problema é que como ele procura o </div>, não discrimina se esse fecho pertence à primeira div, pelo que se tiver outra div dentro dessa, mal apareça o fecho ele dá como terminado o (conteudo), e é isto que eu não quero. Queria que ele me soubesse identificar as tags div dentro da que tem a class editable de modo a apanhar tudo em vez de apenas uma porção.

Share this post


Link to post
Share on other sites
pedrotuga

Não tenhas medo, funciona bem até com html. A não ser que tenhas por exemplo uma tag por fechar. Mas isso a tua aplicação tem que ser capaz de dar conta, de outra forma podes abrir a porta a falhas de segurança graves.

Share this post


Link to post
Share on other sites
subkiller

desculpem estar aqui a expor outra duvida, mas alguem me pode explicar o que é fazer parse a um elemento HTML ou a uma div como é o caso?

Share this post


Link to post
Share on other sites
yoda

Não tenhas medo, funciona bem até com html. A não ser que tenhas por exemplo uma tag por fechar. Mas isso a tua aplicação tem que ser capaz de dar conta, de outra forma podes abrir a porta a falhas de segurança graves.

Consegui fazer parse das divs como queria, mas agora tenho outro problema (nunca acabam :cheesygrin:), caso tenha a seguinte estrutura :

<div class="editable">
texto1
<div></div>
texto2
</div>

Neste caso consigo sacar até os NODE_TEXT separados conforme a sua ordem de apresentação, problema é arranjar um esquema em que consiga montar isto seguido para posterior edição.

@subkiller

Parse (aka syntactic analysis) é um processo de análise de uma sequência de tokens, como palavras e tags xml por exemplo, para determinar a sua estrutura.

Share this post


Link to post
Share on other sites
subkiller

hummm, tu fazes um parse para modificar o conteudo do css a partir do backoffice nao é?

Share this post


Link to post
Share on other sites
subkiller

entao tu usas a funçao preg_match_all para fazer isso nao é? foi o que percebi pelo que dissseste no primeiro post....

e eu tive a ver essa funçao no php.net mas nao percebi muito bem como ela funciona...

Share this post


Link to post
Share on other sites
yoda

entao tu usas a funçao preg_match_all para fazer isso nao é? foi o que percebi pelo que dissseste no primeiro post....

e eu tive a ver essa funçao no php.net mas nao percebi muito bem como ela funciona...

preg_match usa regex, que é algo comum a muitas linguagens de programação .. É um pouco difícil perceber a syntax do regex, mas quando se conhece bem, é poderoso.

Share this post


Link to post
Share on other sites
subkiller

so mais uma coisa e desculpa estar a chatear-te...

preg_match_all('/<div[^>]*class="[^"]*(editable){1}[^"]*"[^>]*>(.*?)<\/div>/si', $this->xhtml, $parts, PREG_SET_ORDER);

para que serve o que tu metes no primeiro parametro?

Share this post


Link to post
Share on other sites
pedrotuga

subkiller, abre um tópico sobre isso se tiveres dúvidas. Assim estás a 'roubar' o tópico do yoda.

yoda, não percebi o problema, podes ilustrar melhor?

Share this post


Link to post
Share on other sites
yoda

@pedrotuga

Já desisti desse método, não tava a dar com nada. Mesmo com xpath, não consegui arranjar forma de unir todo o conteúdo sacado numa string. O que usei para criar um array foi isto :

$doc = new DOMDocument('1.0', 'ISO-8859-1');
$doc->loadHTMLFile(PATH.'teste.html');

$xpath = new DOMXpath($doc);
$elements = $xpath->query('//div[normalize-space(@cms)="editable"]');

global $data;

if (!is_null($elements)) {
foreach ($elements as $element) {

	childs($element, 0, true);
}
}

function childs($node, $level = 0, $reset = false)
{
global $data;
static $i;

if ($reset === true) $i = 0;  

$attr = null;
if($node->nodeType != XML_TEXT_NODE)
{
	if( $node->nodeType == XML_ELEMENT_NODE )
	{
		$attributes = $node->attributes;
		foreach($attributes as $attribute)
			$attr[] = array('name' => $attribute->name, 'value' => $attribute->value);
	}
	$data[$level][$i++] = array('name' => $node->nodeName, 'attributes' => $attr);
}
else
	$data[$level][$i++] = array('name' => $node->nodeName, 'data' => $node->data);
}

$cnodes = $node->childNodes;
if (count($cnodes) > 0)
{
	$level++ ;
	foreach($cnodes as $cnode)
		childs($cnode, $level);
	$level = $level - 1;
}
}

echo var_dump($data);

.. que cria um array com a informação pretendida, excepto o parentNode, que preciso para concatenar os conteúdos no local certo. Como a função é recursiva, não tenho a certeza como fazer para que me passe isso por parametro.

Also, o que estava a dizer é que se tiver este caso :

<div class="editable">
texto1
<div></div>
texto2
</div>

.. ele vai identificar 2 text nodes, texto1 e texto2 em separado, o que até é conveniente para poder inserir os restantes elementos no local correcto. Só me falta mesmo conseguir sacar o parent de cada elemento para poder concatenar no final numa string unica.

Share this post


Link to post
Share on other sites
pedrotuga

Infelizmente não domino xpath ou ponto de te poder ajudar mais... talvez o rui carlos ou outra pessoa estaja mais familiarizado com isto.

Mas deve ser possível fazer um query que saca o conteudo TODO da div da classe 'editable' para dentro de uma string.

Share this post


Link to post
Share on other sites
Rui Carlos

Não sei exactamente o que pretendes fazer, mas se vais transformar um XML, usares XSLT também pode ser uma boa ideia (continuas a usar XPath pelo meio). É claro que tudo depende da complexidade das operações que pretendes realizar.

O XPath é bom para ir buscar uma parte do XML, mas não estou a ver como o usar para substituir esse pedaço. Para essa tarefa sempre usei XSLT.

Share this post


Link to post
Share on other sites
yoda

Infelizmente não domino xpath ou ponto de te poder ajudar mais... talvez o rui carlos ou outra pessoa estaja mais familiarizado com isto.

Mas deve ser possível fazer um query que saca o conteudo TODO da div da classe 'editable' para dentro de uma string.

Duvido que seja, estou farto de procurar e não encontro nada .. Só se não usar DOM XML.

Voltando ao regex, arranjei um que faz "quase" o que eu queria, mas por alguma razão não estou a conseguir adaptar à procura das divs com base no class="editable" :

/<div\b[^>]*>(?>(?:[^<]++|<(?!\/?div\b[^>]*>))+|(?R))*<\/div>/

este era o pattern que tinha antes :

/<div[^>]*class="[^"]*(editable){1}[^"]*"[^>]*>(.*?)<\/div>/si

Share this post


Link to post
Share on other sites
Rui Carlos

Sim, o conceito é o mesmo .. mas xhtml é mais sujo, por causa das html entities e afins ..

Uma linguagem é XML se cumprir um conjunto de requisitos. O XHTML cumpre esses requisitos, logo é XML, ponto!

Certamente que podes inventar uma linguagem que seja XML ainda mais complexa que o XHTML.

A partir do momento que XHTML é XML, podes usar as tecnologias que tens disponíveis para manipular XML (como XPath ou XSLT) para manipular XML.

Não percebi bem em que aspecto é que XSL ajuda neste caso específico.

O XSLT permite-te especificar transformações a aplicar a ficheiros XML. Parece-me que era isso que querias fazer. Mas como disse, tudo depende da complexidade das transformações.

Se deres uma descrição mais pormenorizada daquilo que queres fazer, posso tentar dar mais alguma informação sobre a viabilidade de usar XSLT.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.