Atividade de Laboratório no. 10

Descrição do Problema
Uma página HTML
Representação de uma página
A Árvore
Localização das tags
A atividade
As Funções
Exemplos de uso
Exemplo de Entrada para 'exemplo2.c'
Exemplo de Saída
Código
Data de Entrega

MC 202 EF - Segundo semestre de 2008

Geração de Página HTML

Descrição do Problema

Ao se desenvolver uma aplicação disponibilizada aos usuários através da web, normalmente se depara com o problema de construir páginas HTML cujo conteúdo é definido dinâmicamente pela aplicação. Essas páginas são chamadas páginas de conteúdo dinâmico ou simplesmente 'páginas dinâmicas'. Diversas soluções têm sido usadas para o problema, sendo que as mais usadas se baseiam em combinar texto HTML com a linguagem de programação usada. Esse é o caso de soluções como JSP e ASP (JSP mistura HTML com Java e ASP mistura HTML com VisualBasic).

Essas soluções, embora produzam resultados rápidos, levam à construção de um software difícil de ser mantido uma vez que tendem a misturar a lógica da aplicação com a apresentação. Isso vai contra as práticas modernas de engenharia de software, que propõem justamente a organização da arquitetura em camadas, onde 'lógica de negócios' e 'apresentação' tipicamente são colocadas em camadas distintas.

Uma alternativa é a usar uma estrutura de dados que represente a 'página dinâmica' sendo construída e que é modificada pela aplicação através de funções específicas. Uma vez que essa estrutura esteja representando a página na sua forma final, ela é percorrida para que a página seja efetivamente gerada (a página HTML gerada nada mais é que um arquivo texto).

Uma página HTML

Uma página HTML é formada por elementos delimitados por marcadores (etiquetas ou, em ingles, tags), da forma
 <marcador> ... conteúdo ... </marcador>

Os marcadores são indicações para o navegador sobre a forma pela qual o conteúdo deve ser apresentado. A linguagem HTML define um conjunto de marcadores, cada um com um significado específico.

O conteúdo de um marcador é uma seqüência de elementos que podem ser
  • texto
  • comentário
  • marcador(tag)
  • Um exemplo simples de página HTML:
     <HTML>
    <HEAD>
    <TITLE>
    Exemplo de Página HTML
    </TITLE>
    </HEAD>
    <BODY>
    Este é apenas um exemplo de página
    HTML muito simples. Experimente copiá-lo num
    arquivo "exemplo1.html" e abri-lo num
    navegador para ver o efeito.
    </BODY>
    </HTML>

    Neste exemplo são usados os principais elementos de uma página HTML:
  • descrição da página:
  • é delimitada pelos marcadores <HTML> e </HTML>
  • cabeçalho:
  • a página contém um cabeçalho delimitado por <HEAD> e </HEAD> e um 'corpo' delimitado por <BODY> e </BODY>
  • 'corpo da página':
  • deve conter a parte da página que será apresentada na tela principal do navegador. Neste caso, ele contém apenas um texto.
  • título:
  • o cabeçalho contém o título da página, delimitado por <TITLE> e </TITLE>. Na apresentação da página pelo navegador, esse título será apresentado na barra superior da tela do navegador.
  • formatação:
  • a formatação do texto da página é irrelevante na apresentação da página. Indentação, fins de linha, espaços em branco, são ignorados pelo navegador, que usa apenas os marcadores como orientação para apresentar a página.
  • marcadores fechados e abertos:
  • alguns marcadores, como por exemplo <BR>, não têm o marcador de fechamento correspondente (nesse caso, </BR>).
  • atributos:
  • um marcador pode ainda ter um conjunto de atributos, como por exemplo
     <FONT name=“arial” size=“24” colour=“black” >

    Se você não estiver familiarizado com HTML, muitos tutoriais estão disponíveis na rede, como por exemplo

    http://www.icmc.usp.br/ensino/material/html/basico.html

    http://members.tripod.com/~shibolete/Passo1.html

    http://www.w3schools.com/html/default.asp

    Representação de uma página

    Considerando a estrutura de uma página HTML, a representação natural para a mesma seria uma árvore geral: cada 'elemento' da página pode ter vários filhos, dos cada um pode ser uma tag. No caso de ser uma tag, ele pode ter vários filhos, cada um por sua vez podendo ser uma tag. Nessa linha a página do exemplo acima poderia ser representada de forma simplificada por uma árvore como mostrada abaixo:

    A Árvore

    Conforme explicado acima, cada nó da árvore irá representar um 'elemento' da página que pode ser
  • um texto
  • um comentário
  • um marcador
  • Uma possível representação para um nó da árvore seria a seguinte:
     /* tipos possíveis para um nó da árvore */
    typedef enum {TEXT, COMMENT, TAG } NodeType;

    /* apontador para um nó da árvore */
    typedef struct HTMLNode *NodePtr;

    /* estrutura para cada nó da árvore */
    typedef struct HTMLNode {
    NodeType type; /* tipo do nó */
    HTMLContent content; /* conteúdo do nó */
    NodePtr next; /* apontador para o próximo */
    } HTMLNode;

    O campo type será usado para indicar o tipo do nó. O campo content pode ser uma estrutura com partes variantes (union), definida como a seguir:
     /* descrição de uma tag */
    typedef struct {
    char *name; /* nome da tag */
    int closed; /* 0 = 'aberta', 1 = 'fechada' */
    AttribPtr attrList; /* lista de atributos */
    NodePtr childList; /* lista de 'filhos'
    } TagType;


    typedef union {
    char *text; /* texto */
    char *comment; /* comentario */
    TagType tag; /* tag */
    } DadosComplem;

    A lista de atributos pode ser descrita por nós do seguinte tipo:
     typedef struct AttrType *AttrPtr;
    typedef struct {
    char *name; /* nome do atributo */
    char *value; /* valor do atributo */
    } AttrType;

    Localização das tags

    A construção da página HTML baseada numa estrutura que a representa vai exigir que se localize as partes da página. Felizmente HTML tem um recurso que pode ajudar nesse caso: o atributo 'id', que não interfere na apresentação da página pelo navegador. Esse atributo pode ser usado para localizar os elementos da página aos quais se deseja agregar novos elementos dinamicamente. Para isso, é necessário que cada tag tenha uma identificação única. Uma vez que as tags tenham essa identificação, a sua localização pode ser feita por meio de um mecanismo de busca como por exemplo árvore de busca ou tabela de 'hashing'. Nesta atividade, deverá ser usada uma tabela de hashing. A tabela de hashing fará referências aos nós da árvore que representa a página, conforme mostrado na figura abaixo.

    As definições necessárias ao uso de hashing são as seguintes:
     /* apontador para um nó da tabela de hashing */
    typedef struct HashNode *HashNodePtr;

    /* nó da tabela de hashing */
    typedef struct HashNode {
    char *key; /* chave de busca */
    void *valueptr; /* valor associado */
    HashNodePtr next; /* apontado p/ próximo */
    } HashNode;

    /* tamanho da tabela de hashing */
    #define HASHSIZE 128

    /* inicia uma tabela de hashing */
    void initHashTable(HashTable);

    /* tipo da tabela de hashing */
    typedef HashNodePtr HashTable[HASHSIZE];

    /* insere (chave,valor) numa tabela de hashing */
    void hashInsert(char*, void*, HashTable);


    /* busca pelo valor associado a uma chave */
    void *hashSearch(char *, HashTable);

    A atividade

    Para esta atividade de laboratório já estão definidos
  • 'htmlib.h':
  • arquivo contendo as definições dos tipos de dados a serem usados e os cabeçalhos das funções para manipular a representação da página que você deve implementar.
  • 'hashlib.h':
  • arquivo contendo as definições dos tipos de dados e os cabeçalhos das funções para operar com a tabela de hashing, que devem ser implementadas em 'hashlib.c'.
  • 'exemplo1.c' e 'exemplo2.c':
  • 'programas de aplicação' exemplo, que fazem uso das funções definidas em 'htmlib.h', e que você deverá implementar, para gerar páginas HTML.

    A sua tarefa consiste em implementar, num arquivo 'htmlib.c', as funções que realizam as operações definidas em 'htmlib.h' e num arquivo 'hashlib.c', as funções que realizam as operações definidas em 'hashlib.h'.

    As Funções

    As funções a serem implementadas são as seguintes
     HTMLPagePtr newPage(char *);

    Cria um descritor de página HTML contendo uma tabela de hashing vazia e um descritor para a tag <HTML>, com atributo "id", cujo valor é passado como parâmeetro para a função.
     void insertElement(HTMLPagePtr, char *, NodePtr);

    Insere um elemento numa página HTML, como 'filho' da tag cuja identificação é passada como parâmetro. Os parâmetros são:
  • apontador para a página (HTMLPagePtr)
  • identificação da tag à qual o novo elemento será agregado (char *)
  • apontador para o elemento a ser inserido (NodePtr).
  • Atenção: o elemento sendo insererido pode ser uma tag que tem o atributo "id". Nesse caso, o valor do atributo deve ser inserido na tabela de hashing da página, associado ao elemento.
     void addAttrib(NodePtr, char *, char*);

    Agrega um atributo a um elemento (só faz sentido se esse elemento for uma tag). Parâmetros:
  • Apontador para o elemento
  • Nome do atributo (char *)
  • Valor do Atributo (char *)
  •  void appendChild(NodePtr, NodePtr);

    Agrega um 'filho' a um elemento (só faz sentido se for uma tag). Parâmetros:
  • Apontador para a tag à qual o elemento será agregado (NodePtr)
  • Apontador para o elemento a ser agregado como filho.
  •  NodePtr newTag(char *name, int closed);

    Cria um elemento que descreve uma tag HTML. Parâmetros:
  • nome da tag (char *)
  • indicação de tag fechada ou aberta (int)
  •  NodePtr newComment(char *);

    Cria um elemento do tipo comentário. Parâmetro:
  • texto a ser associado ao comentário (char *)
  •  NodePtr newText(char *);

    Cria um elemento do tipo texto. Parâmetro:
  • conteúdo do texto (char *);
  •  void writePage(HTMLPagePtr, char *);

    Escreve o texto correspondente a uma página HTML descrita por um 'descritor de página'. Parâmetros:
  • apontador para o descritor de página (HTMLPagePtr).
  • nome do arquivo de saída.
  • Para escrever como HTML o conteúdo de um elemento de uma página, se esse elemento for do tipo
  • TEXT: copiar o texto correspondente na saída
  • COMMENT: copiar o texto correspondente na saída entre '<!--' e '-->'
  • TAG:
  • Escrever o nome da tag entre '<' e '>'. Para cada filho da tag, escrever o texto HTML correspondente (recursivamente). Se a tag for uma tag fechada, fechar a tag com '</nome da tag >'.

    Exemplos de uso

    O código abaixo mostra como a biblioteca 'htmlib' pode ser usada para gerar uma página simples, 'exemplo1.c'.
    #include 
    #include
    #include
    #include "htmlib.h"

    /* insere uma referência (hyperlink) numa página */
    NodePtr insertRef(HTMLPagePtr page, char *id, char *url, char *text){
    NodePtr p = newTag("a",true);
    addAttrib(p,"href",url);
    appendChild(p,newText(text));
    insertElement(page,id,p);
    return p;
    }
     
    /* monta uma página contendo o conjunto mínimo de elementos */
    HTMLPagePtr makeTemplate(){
    HTMLPagePtr myPage = newPage("page");
    NodePtr myHead = newTag("HEAD",true);
    NodePtr myTitle = newTag("TITLE",true);
    NodePtr myBody = newTag("BODY",true);
    addAttrib(myHead,"id","head");
    addAttrib(myBody,"id","body");
    addAttrib(myTitle,"id","title");
    insertElement(myPage,"page",myHead);
    insertElement(myPage,"page",myBody);
    insertElement(myPage,"head",myTitle);
    return myPage;
    }

    /* monta uma página exemplo */
    HTMLPagePtr makePage1(){
    HTMLPagePtr myPage = makeTemplate();
    insertElement(myPage,"title",newText("Página exemplo"));
    insertHeader(myPage,"body","h1","MC 202 - turmas E e F");
    insertHeader(myPage,"body","h2","Segundo semestre de 2004");
    insertHeader(myPage,"body","h3","Atividade de Laboratório no. 9");
    insertElement(myPage,"body",
    newText("Este é apenas um exemplo de página HTML gerada por programa. ")
    );
    insertElement(myPage,"body",newTag("BR",false));
    insertElement(myPage,"body",newText("Benvindo ao "));
    insertRef(myPage,"body","http://www.ic.unicamp.br","IC-UNICAMP");
    return myPage;
    }

    int main(int argc, char *argv[]) {
    HTMLPagePtr p = makePage1();
    writePage(p,"pagina1.html");
    return 0;
    }

    O programa 'exemplo2.c' mostra um código mais completo.

    Exemplo de Entrada para 'exemplo2.c'

    O arquivo de entrada, 'ativ10.txt', usado por 'main.c' para gerar uma página HTML, é um exemplo de entrada possível para a aplicação de testes 'exemplo2.c'.

    Exemplo de Saída

    Esta página HTML que você está lendo, foi gerada pelo programa 'exemplo2.c' e constitui assim um bom exemplo de saída.

    Código

    O código para esta atividade está disponível em http://www.ic.unicamp.br/~vanini/codAtiv10.zip

    Data de Entrega

    A tarefa deverá ser entregue até 17/11/2008