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

yoda

desafio regex

34 mensagens neste tópico

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 ..  :hmm:

Alguém tem dicas?

Obrigado

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Com regexes (plural) é possível claro. Com uma só é que não te safas porque tens que tar ciente da estrutura do HTML, é uma árvore.

A ferramenta indicada para isso chama-se Xpath. O rui carlos afixou aqui um link para um documento que explica isso muito bem em bom português:

http://www.portugal-a-programar.pt/forums/topic/0-find-topic/?do=findComment&comment=176773

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@pedrotuga

Já usei DomXPath em outros projectos, mas não tenho tantas certezas quanto à sua viabilidade neste caso. Xhtml comparado com xml é um bocado "sujo". De qualquer modo, vou dar uma hipótese à tua ideia.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Nem por isso, mas ao ler umas coisas aí veio-me a ideia de fazer um preg_replace temporário a tudo o que seja divs dentro da div editable, para outro nome, de forma a nao colidirem .. É uma solução meio à pedreiro mas é capaz de funcionar :confused:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

Não, faço parse para identificar a estrutura dos ficheiros html

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@Rui Carlos

Não é bem xml, é xhtml .. O ideal era conseguir por regex, mas a esta altura já vai como der .. Em última instância uso jQuery para sacar as divs que quero on-the-fly para o editor final.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@Rui Carlos

Não é bem xml, é xhtml.

XHTML é XML.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

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.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não quero transformar nada no xhtml, quero apenas retirar porções do mesmo .. como referi no primeiro post, quero sacar todas as divs com class = editable, e respectivo conteúdo.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora