d`ilton moreira silveira mapeamento de dtds para...
TRANSCRIPT
D`Ilton Moreira Silveira
Mapeamento de DTDs para Esquemas Lógico-Relacionais
RELATÓRIO FINAL TCC
Palmas – TO 2003
D`Ilton Moreira Silveira
Mapeamento de DTDs para Esquemas Lógico-Relacionais
“Monografia apresentada como
requisito parcial da disciplina Prática de
Sistemas de Informação II (TCC) do
curso de Sistemas de Informação,
coordenada pela Profª. M.Sc. Deise de
Brum Saccol”
Palmas – TO 2003
D`ILTON MOREIRA SILVEIRA
Mapeamento de DTDs para Esquemas Lógico-Relacionais
“Monografia apresentada como
requisito parcial da disciplina Prática de
Sistemas de Informação II (TCC) do
curso de Sistemas de Informação,
coordenada pela Profª. M.Sc. Deise de
Brum Saccol”
Aprovado em dezembro de 2003.
BANCA EXAMINADORA
Profª. Deise de Brum Saccol, M.Sc.
Centro Universitário Luterano de Palmas
Prof°. Eduardo Kessler Piveta, M.Sc.
Centro Universitário Luterano de Palmas
Prof°. Fabiano Fagundes, M.Sc.
Centro Universitário Luterano de Palmas
AGRADECIMENTOS
Prezados leitores, alguns anos atrás eu tinha um sonho que por alguns motivos eu
pensava que não ia realizá-lo. Um certo dia me ligaram e deram-me uma notícia, eu estava
sendo chamado para fazer a minha matrícula na faculdade, nesse instante eu não sabia se o
meu sonho estava se tornado realidade ou em um pesadelo, pois eu não tinha dinheiro para
pagar a matriculo e muito menos as mensalidades. Eu, naquele instante tomei uma decisão,
peguei dinheiro emprestado para pagar a matrícula e me ingressar na vida acadêmica. E
graças a Deus, estou nesse momento escrevendo os agradecimentos do meu trabalho de
conclusão de curso universitário.
Agradeço primeiramente a Deus, que nunca me abandonou. E, nos momentos mais
difíceis da minha vida, Ele sempre tem me ajudado fazendo com que eu enxergue
caminhos que me levam a vitória. E graças a Ele eu estou concretizando um sonho dentre
vários outros que serão realizados.
Agradeço ao meu pai Neuton, posso dizer o melhor pai do mundo. Ele sempre está
ao meu lado pronto para me ajudar. Pai, te agradeço pelo senhor ter me ajudado a realizar
esse sonho. Agradeço também a minha mãe, Hilda. Mãe, obrigado pelas suas orações, e eu
digo que a senhora é a melhor mãe do mundo.
Agradeço aos meus irmãos, Denilton , Castilio, e Lucinéia, obrigado por fazerem
parte da minha vida.
Professor Fabiano, obrigado pelos momentos de distração no LABMIDIA, pelas
broncas nos momentos em que eu estava precisando, pelos incentivos, obrigado também
por ter me ajudado a escrever parte da minha história dentro da faculdade. Você é uma
pessoa especial que mora dentro do meu coração.
Professora Parcilene, obrigado pela tua amizade e pelo conhecimento que você me
proporcionou, sou muito grato a você. Que Deus possa vir te recompensar.
Professora Deise, a professora queridinha. Deise, foi muito bom trabalhar no
mesmo local que você, ser seu aluno, e é claro ser o seu orientando. Obrigado por fazer
parte de uma das minhas conquistas. Que a graça de Deus esteja sobre você.
Agradeço também a todos os demais professores, pela amizade, pelo conhecimento
a mim proporcionado. Que Deus possa vir recompensá-los.
Agradeço ainda as seguintes pessoa, Kênia, Polly, Elaine, Nábia, Suellen,
Anderson, Michael, Marcus, Danilo, Álvaro, Bruno. Vocês são pessoas especiais que
moram dentro do meu coração.
“O temor do Senhor é o princípio da sabedoria...”
Salmos 111:10a
SUMÁRIO
1. INTRODUÇÃO.......................................................................................... 13
2. REVISÃO DE LITERATURA ................................................................. 14
2.1 DADOS SEMI-ESTRUTURADOS E DADOS ESTRUTURADOS ........................ 14
2.2 EXTENSIBLE MARKUP LANGUAGE (XML) ............................................. 15
2.3 DOCUMENT TYPE DEFINITION (DTD) .................................................... 16
2.4 ARMAZENAMENTOS DE DOCUMENTOS XML.......................................... 19
2.5 USO DE SGBDS RELACIONAIS PARA O ARMAZENAMENTO DE XML........ 20
2.5.1 DB2.................................................................................................. 21
2.5.2 SQL Server 2000 .............................................................................. 22
2.5.3 Oracle 9i .......................................................................................... 22
2.6 GERAÇÃO DE ESQUEMA LÓGICO RELACIONAL A PARTIR DE DTD............. 23
2.6.1 Primeira abordagem ........................................................................ 23
2.6.2 Segunda abordagem ......................................................................... 25
2.6.3 Terceira abordagem ......................................................................... 27
2.6.4 Quarta abordagem ........................................................................... 32
3. MATERIAIS E MÉTODOS...................................................................... 35
4. RESULTADOS E DISCUSSÕES.............................................................. 36
4.1 PROPOSTA............................................................................................. 36
4.2 ESTUDO DE CASO .................................................................................. 37
4.3 REPRESENTAÇÃO DA DTD EM FORMATO XML ...................................... 42
4.4 ALGORITMO DE GERAÇÃO DE ESQUEMAS LÓGICOS A PARTIR DA DTD ..... 43
4.4.1 Elementos PCDATA ......................................................................... 44
4.4.2 Elemento complexo........................................................................... 47
4.4.3 Elemento vazio ................................................................................. 50
4.4.4 Elemento misto ................................................................................. 52
4.5 SISTEMA IMPLEMENTADO ...................................................................... 56
4.6 COMPARAÇÃO ENTRE OS ALGORITMOS APRESENTADOS NA REVISÃO DE
LITERATURA E O ALGORITMO DESENVOLVIDO NESSE TRABALHO ............. 58
5. CONSIDERAÇÕES FINAIS E TRABALHOS FUTUROS..................... 61
Lista de Abreviaturas
DTD Document Type Definition
SGBD Sistema Gerenciador de Banco de Dados
SQL Structured Query Language
SGML Standard Generalized Markup Language
XML extensible Markup Language
W3C World Wide Web Consortium
Lista de Figuras
FIGURA 1 – EXEMPLO DE UM DOCUMENTO XML.............................................................. 16
FIGURA 2 - EXEMPLO DE UMA DTD QUE VALIDA O DOCUMENTO XML DA FIGURA 1 ......... 18
FIGURA 3 – DTD EXEMPLO PARA AS ABORDAGENS DE MAPEAMENTO. .............................. 24
FIGURA 4 – ESQUEMA LÓGICO RELACIONAL GERADO SEGUNDO A DTD DA FIGURA 3
(ABORDAGEM 1) ....................................................................................................... 25
FIGURA 5 – GRAFO DA DTD DA FIGURA 3 (SEGUNDA ABORDAGEM) ................................. 26
FIGURA 6 – ESQUEMA LÓGICO RELACIONAL GERADO SEGUNDO A DTD DA FIGURA 3
(ABORDAGEM 2). ...................................................................................................... 27
FIGURA 7 – REGRAS PARA ELIMINAR A COMPLEXIDADE DOS DTDS (LU ET AL 2003). ....... 28
FIGURA 8 – ALGORITMO INLINING (LU ET AL 2003).......................................................... 29
FIGURA 9 – GRÁFICO INLINING DA DTD (LU ET AL 2003) ................................................ 30
FIGURA 10 – GRAFO INLINING DA DTD DA FIGURA 3 ........................................................ 30
FIGURA 11 – ESQUEMA LÓGICO RELACIONAL GERADO SEGUNDO A DTD DA FIGURA 3
(ABORDAGEM 3) ....................................................................................................... 32
FIGURA 12 – DOCUMENTO XML VÁLIDO SEGUNDO A DTD DA FIGURA 3.......................... 33
FIGURA 13 – GRAFO DO DOCUMENTO XML DA FIGURA 12 ............................................... 33
FIGURA 14 – ARQUITETURA DO SISTEMA ......................................................................... 36
FIGURA 15 – DTD PARA PUBLICAÇÕES DE LIVROS E ARTIGOS ........................................... 38
FIGURA 16 – DOCUMENTO XML VÁLIDO SEGUNDO A DTD DA FIGURA 15 – EXEMPLO 01 . 39
FIGURA 17 – DOCUMENTO XML VÁLIDO SEGUNDO A DTD DA FIGURA 15 – EXEMPLO 02 . 40
FIGURA 18 – DOCUMENTO XML VÁLIDO SEGUNDO A DTD DA FIGURA 15 – EXEMPLO 03 . 41
FIGURA 19 – DTD MSG ................................................................................................... 42
FIGURA 20 – REPRESENTAÇÃO XML DA DTD DA FIGURA 19 ........................................... 43
FIGURA 21 – INICIO DO ALGORITMO................................................................................. 44
FIGURA 22 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO PCDATA E MONOVALORADO.
................................................................................................................................ 45
FIGURA 23 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO PCDATA E MULTIVALORADO.
................................................................................................................................ 46
FIGURA 24 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO FILHO MULTIVALORADO E
ELEMENTO PAI MULTIVALORADO OU ELEMENTO FILHO MONOVALORADO E ELEMENTO PAI
MULTIVALORADO. ...................................................................................................... 48
FIGURA 25 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO FILHO MULTIVALORADO E
ELEMENTO PAI MONOVALORADO. ................................................................................. 49
FIGURA 26 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO FILHO MONOVALORADO E
ELEMENTO PAI MONOVALORADO. ................................................................................. 49
FIGURA 27 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO VAZIO. .............................. 51
FIGURA 28 – INICIO DO ALGORITMO QUE TRATA DE ELEMENTO MISTO................................ 53
FIGURA 29 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO MISTO – QUANDO O FILHO
DO ELEMENTO MISTO É PCDATA. .............................................................................. 53
FIGURA 30 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO MISTO – QUANDO O FILHO
DO ELEMENTO MISTO POSSUI FILHOS. ...................................................................... 54
FIGURA 31 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO MISTO – QUANDO O FILHO
DO ELEMENTO MISTO FOR UM PCDATA. ................................................................... 55
FIGURA 32 – PARTE DO ALGORITMO QUE TRATA DE ELEMENTO MISTO – QUANDO O FILHO
DO ELEMENTO MISTO FOR UM ELEMENTO VAZIO......................................................... 56
FIGURA 33 – INTERFACE DO SISTEMA............................................................................... 57
FIGURA 34 – MODELO LÓGICO RELACIONAL GERADO A PARTIR DA DTD DA FIGURA 3. ..... 58
Lista de Tabelas
TABELA 1 – EXEMPLO TABELA BASEADO EM ARCO – COM BASE NO GRAFO DA FIGURA 13.. 34
TABELA 2 – TAUTOR – MAPEAMENTO COM INLINING ....................................................... 34
TABELA 3 – TNOME – MAPEAMENTO COM INLINING.......................................................... 34
RESUMO
Esse trabalho busca definir um algoritmo capaz de mapear uma DTD (Document
Type Definition) para um modelo lógico relacional. Após a definição desse
algoritmo, implementá-lo em uma linguagem de programação, desenvolvendo
assim, uma ferramenta que gerará um script SQL do modelo lógico relacional, o
qual poderá ser executado, como por exemplo, no SQL Server.
ABSTRACT
This work aims to define an algorithm to map a DTD (Document type definition) to
a relational logical model. After the definition of this algorithm, to implement it in a
programming language. In this way, a tool will be developed to generate a SQL script,
which can be executed over SQL Server, for instance.
13
1. INTRODUÇÃO
Sistemas Gerenciadores de Banco de Dados (SGBDs) específicos para documentos
XML (extensible Markup Language) ainda estão em fase de amadurecimento e são
relativamente pouco utilizados, principalmente devido ao pequeno número de produtos
comerciais disponíveis. Atualmente, para o armazenamento de documentos XML, SGBDs
relacionais têm sido mais usados. Para isso, faz-se necessário um mapeamento de
documentos XML para o modelo relacional. Várias abordagens têm sido utilizadas neste
mapeamento, dentre elas, a criação de esquemas lógicos relacionais a partir de DTDs.
Nesse trabalho foi desenvolvido um algoritmo capaz de realizar o mapeamento de
DTDs para modelos lógico relacionais, e uma aplicação que gera um script SQL
(Structured Query Language), tendo como base o algoritmo proposto nesse trabalho. Uma
vez que se tenha o script SQL gerado pela aplicação, o usuário pode executá-lo no SQL
Server (SGBD utilizado neste trabalho), criando um banco de dados com todas as tabelas
definidas no script, assim como os relacionamentos entre elas.
Atualmente, existem várias abordagens sobre algoritmos que fazem o mapeamento
de DTDs para um modelo lógico relacional. Dentre eles, pode-se citar as seguintes
referências: (BOU 2001), (SHA 99) e (LU et al 2003).
O trabalho está organizado da seguinte forma: o capítulo 2 apresenta a revisão de
literatura que está subdividida em: Dados Semi-Estruturados e Dados Estruturados; uma
descrição sobre XML; DTDs; uma demonstração de armazenamento de documentos XML;
uma abordagem sobre o uso de SGBDs relacionais para o armazenamento de documentos
XML; e também são apresentados alguns algoritmos que realizam o mapeamento de DTDs
para modelo lógico relacional. No capítulo 3 têm-se os materiais e métodos. O capítulo 4
relata os resultados e discussões. E o 5 mostra as considerações finais e os trabalhos
futuros.
14
2. REVISÃO DE LITERATURA
Este capítulo apresenta uma abordagem sobre dados semi-estruturados e
estruturados, XML, DTD, armazenamento de documentos XML, o uso de SGBDs
Relacionais para o armazenamento de XML e por fim sobre geração de esquemas lógicos
relacionais a partir de DTDs.
2.1 Dados Semi-estruturados e Dados Estruturados
Atualmente, têm-se muitas informações disponíveis em sistemas eletrônicos. Essas
informações encontram-se em diversos formatos, como textos, imagens, tabelas etc. Neste
trabalho são citados dois formatos de dados: semi-estruturados e estruturados.
Para dados semi-estruturados têm-se um exemplo clássico que são os dados da
Web, como bibliotecas digitais, sites de comércio eletrônico etc. Este tipo de dado
geralmente não possui um esquema associado no momento de sua criação.
Dados semi-estruturados apresentam as seguintes características (MELLO et al,
2000):
• Definição de esquema a posteriori: esquemas de dados são criados após a
existência dos dados;
• Estrutura irregular: os dados estão organizados de formas diferentes;
• Estrutura implícita: mesmo existindo uma estrutura para os dados, “essa
estrutura está implícita na forma como os dados são apresentados. É
necessário realizar uma computação para obter essa estrutura”;
• Estrutura parcial: apenas parte dos dados seguem uma estrutura;
• Estrutura extensa: “a ordem de magnitude de uma estrutura para estes dados
é grande, uma vez que os mesmos são muito heterogêneos. Supondo
diferentes formatos para um curriculum vitae, uma união de atributos
significativos em cada formato pode produzir um esquema extenso”;
15
• Estrutura evolucionária: há uma modificação constante tanto da estrutura
dos dados quanto dos seus valores;
• Estrutura descritiva e não prescritiva: “dada a natureza irregular e
evolucionária dos dados semi-estruturados, as estruturas de representação
implícitas ou explícitas normalmente se restringem a descrever o estado
corrente de poucas ocorrências de dados similares. Desta forma, não é
possível prescrever esquemas fechados e muitas restrições de integridade
com relação à semântica dos atributos. Um sinônimo para estrutura
descritiva é estrutura indicativa”;
• Distinção entre estrutura e dados não é clara: a estrutura depende da
descrição dos dados, tornando a distinção entre estrutura e valor confusa.
Ao contrário de dados semi-estruturados, os dados estruturados possuem um
esquema definido no momento de sua criação; têm-se como exemplo de dados estruturados
os modelos de dados relacionais, orientados a objetos etc.
Dados estruturados possuem as seguintes características (MELLO et al, 2000):
• Esquema pré-definido: esquemas de dados são definidos antes da existência
dos dados;
• Esquema independente dos dados: a estrutura dos dados não depende dos
dados para existir;
• Estrutura reduzida: a estrutura não vária dentro de um mesmo esquema;
• Fracamente evolutiva: não sofre mudanças em sua estrutura freqüentemente;
• Distinção entre estrutura e dados: a estrutura não depende da descrição dos
dados, tornando a distinção lógica entre estrutura e valor clara;
No próximo tópico têm-se uma breve abordagem sobre XML, uma linguagem de
representação de dados.
2.2 eXtensible Markup Language (XML)
Documentos XML seguem uma estrutura hierárquica, podendo ser divididos em
tags iniciais, tags finais, elementos, atributos etc. Um documento XML pode ser validado
segundo uma DTD. Elementos são representados por tags (<resp></resp>) e cada
elemento pode possuir atributos, elementos e textos. Na figura 1 têm-se um exemplo de um
16
documento XML.
<?xml version='1.0' encoding = "ISO-8859-1"?> <!DOCTYPE listacompra SYSTEM "listacompra.dtd"> <listacompra>
<resp><nome>Kênia</nome>
</resp><local>
<nome>Quarteto</nome></local><compra>
<data dia="12" mes="8" ano="2002"/></compra><setor>
<nome>frios</nome><produto>
<quant>2</quant><unid>kg</unid><nome>queijo</nome><precoant>9.00</precoant><precoat>10.00</precoat>
</produto></setor>
</listacompra>
Figura 1 – Exemplo de um documento XML
A estrutura tem como elemento raiz listacompra, sendo que ele possui vários
elementos filhos. O primeiro é resp e é composto por nome que possui como conteúdo
Kênia. O segundo é local que possui um filho nome com um conteúdo Quarteto. O
próximo filho é o elemento compra, o qual possui um elemento data constituído de três
atributos com seus respectivos valores. E por fim, o elemento setor constituído por dois
elementos filhos, nome e produto.
No próximo tópico têm-se uma breve abordagem sobre DTD.
2.3 Document Type Definition (DTD)
DTDs são utilizadas para descrever a estrutura de documentos XML e podem ser
consideradas esquemas para estes documentos. Para isso, utiliza-se de regras de sintaxe e
de palavras-chaves. A estrutura de uma DTD está dividida em elementos e atributos
(ANDERSON 2001).
17
Elementos são declarados em uma DTD através da tag ELEMENT, sendo que o
conteúdo de um elemento pode ser vazio, outros elementos, misto ou qualquer. Possui
também dois elementos de ordem que são: “,” (seqüência estrita) e “|” (escolha). Para
um elemento, define-se também a sua cardinalidade, operadores que especificam quantas
vezes um elemento pode se repetir em um documento XML. Os operadores podem ser:
“?” (opcional), “*” (zero ou mais vezes) ou “+” (uma ou mais vezes) (ANDERSON
2001).
Conteúdos de um elemento (ANDERSON 2001):
• Elemento vazio: são elementos que não possuem elementos filhos e nem
texto; elementos vazios podem ter atributos e são definidos pela palavra-
chave EMPTY;
• Elemento: a definição do elemento só possui elementos filhos e não contém
texto;
• Elemento misto: é uma mistura de #PCDATA (texto) e elementos;
• Elemento qualquer: é um elemento de conteúdo aberto a qualquer conteúdo
que não viole a sintaxe do XML bem-formado; éb definido pela palavra-
chave ANY.
Atributos complementam e modificam elementos, oferecendo meios de associar
propriedades simples a elementos (ANDERSON 2001). Os atributos de um elemento são
declarados dentro de uma tag ATTLIST seguida pelo nome do elemento.
Existem quatro definições padrões para atributos que são (ANDERSON 2001):
• #REQUIRED: o atributo é obrigatório em cada instância do elemento;
• #IMPLIED: o atributo é opcional em cada instância do elemento;
• #FIXED mais valor padrão: o atributo sempre tem o valor padrão mesmo
não aparecendo no documento;
• Somente valor padrão: se o atributo não aparecer, o valor padrão é
presumido pelo parser. Se o atributo aparecer, pode ter outro valor.
Atributos podem ser dos seguintes tipos (ANDERSON 2001):
• CDATA: string;
• ID: permite um único valor em todo o documento;
• IDREF: Referência a algum elemento que tenha um atributo ID existente no
documento;
18
• IDREFS: Referência a mais de um elemento que tenha um atributo ID
existente no documento;
• ENTITY: nome de uma entidade pré-definida;
• ENTITIES: série de ENTITY;
• NMTOKEN: uma declaração NMTOKEN fica em aberto podendo ser
alterado em qualquer ponto da DTD, ou seja, receber outro valor em outro
elemento;
• NMTOKENS: uma série de NMTOKEN;
• NOTATION: aceita um ou uma série de nomes indicando tipo de anotações
declarados na DTD;
• Valor enumerado: uma série de valores definidos pelo usuário com
finalidade de explicitar os valores possíveis de serem aceitos.
<!ELEMENT listacompra (resp*,local*,compra,setor+,email)><!ELEMENT resp (nome)><!ATTLIST resp id ID #REQUIRED><!ELEMENT nome (#PCDATA)><!ELEMENT local (nome)><!ELEMENT compra (data)><!ELEMENT data EMPTY><!ATTLIST data dia CDATA #REQUIRED
mes (1|2|3|4|5|6|7|8|9|10|12) "1"ano NMTOKENS #REQUIRED>
<!ELEMENT setor (nome,produto+)><!ATTLIST setor id_resp IDREF #REQUIRED><!ELEMENT produto (quant,unid,nome,precoant,precoat)><!ELEMENT quant (#PCDATA)><!ELEMENT unid (#PCDATA)><!ELEMENT precoant (#PCDATA)><!ELEMENT precoat (#PCDATA)><!ELEMENT email EMPTY><!ATTLIST email usuario CDATA #REQUIRED
dominio NOTATION (ulbra-to.br|bol.com.br|yahoo.com.br)"ulbra-to.br">
<!ENTITY site "lista.txt">
Figura 2 - Exemplo de uma DTD que valida o documento XML da figura 1
O exemplo de um elemento pode ser visto em listacompra, que é um
elemento raiz, o qual possui uma lista de elementos que são: resp* (o asterístico “*”
indica a cardinalidade do elemento, ou seja, esse elemento pode repetir zero ou mais vezes
em um mesmo documento), local*, compra, setor+ (o sinal de “+” também indica
19
a cardinalidade do elemento, ou seja, esse elemento pode ocorrer uma ou mais vezes em
um mesmo documento) e o elemento email.
Para exemplificar a definição de um atributo têm-se os atributos dos elementos
data, resp, setor e email. O elemento data é um elemento vazio (definido
pela palavra-chave EMPTY) e possui três atributos que são: dia, do tipo CDATA e é
obrigatório (definido como REQUIRED); mes, definido com uma lista de valores e valor
padrão “1”; e ano, do tipo NMTOKENS. O elemento resp possui um atributo id do ID
e é obrigatório. O elemento setor possui o atributo id_resp do tipo IDREF e também
é obrigatório. Para o elemento email existem dois atributos; um deles (dominio) é do
tipo NOTATION. Para exemplificar uma entidade têm-se a declaração da entidade site.
2.4 Armazenamentos de Documentos XML
Para o armazenamento e posterior acesso a documentos XML, pode-se utilizar
quatro abordagens principais (FLO, 99).
A primeira seria a utilização de repositórios de dados nativos, como por exemplo,
Rufus (SHO, 93), Lore (McH, 97), Tamino (SOFTWARE AG, 1999) e Strudel (FER, 98).
Esses são sistemas voltados especificamente para o armazenamento de documentos XML,
sendo que os mesmos seguem uma estrutura própria para trabalhar com índices, otimização
de consultas etc.
A segunda abordagem é a utilização de um banco de dados orientado a objetos.
Nessa abordagem, são exploradas as técnicas de modelagem orientadas a objetos.
Atualmente, são encontrados alguns sistemas comerciais que suportam essa abordagem,
como, por exemplo, O2 ou Objectsore (CHR 94), e o projeto Monet (ZWO 99).
A terceira abordagem é a utilização de bancos de dados relacionais. Armazenar
documentos XML em um banco de dados relacional implica, primeiramente, em definir o
esquema lógico deste banco. Assim, torna-se necessário realizar o mapeamento entre o
modelo de dados semi-estruturados e o esquema lógico relacional. Os dados XML são
mapeados para tabelas em um modelo relacional; as consultas submetidas aos dados semi-
estruturados são mapeadas para SQL.
A última abordagem é armazenar os documentos XML em arquivos texto. Arquivos
são formados por uma estrutura hierárquica, sendo que, essa estrutura é composta por tags
20
iniciais e tags finais (elementos), atributos, valores de atributos e conteúdo de elementos.
Algumas considerações sobre as abordagens apresentadas (FLO, 99):
Os sistemas nativos deveriam apresentar-se como a melhor alternativa, uma vez que
são construídos especificamente para o armazenamento deste tipo de documento. Como
ainda estão em fase de desenvolvimento, apresentam-se pouco escaláveis.
O mesmo acontece com base de dados orientada a objetos. Ainda estão em fase de
maturidade e tendem a apresentar queda de performance no acesso a bases de dados muito
grandes.
Já os sistemas de bancos de dados relacionais são sistemas maduros e trabalham
bem com uma escala grande de dados. Permitem trabalhar com dados extraídos de
documentos XML e dados tradicionais (estruturados). Além disso, pode ser aproveitada a
SQL na manipulação dos dados.
2.5 Uso de SGBDs relacionais para o armazenamento de XML
Bases de dados relacionais apresentam um esquema pré-definido e uma estrutura
homogênea a nível de atributos e tipos (MELLO et al, 2000). Já para dados semi-
estruturados, ocorre a heterogeneidade para cada ocorrência de dados tanto a nível de
atributos quanto de tipos. “Dada essa heterogeneidade, em geral a estrutura de um dado
semi-estruturado está presente na própria descrição do dado, necessitando ser identificada e
extraída. Estas tarefas são complexas, uma vez que a distinção entre esquema e dados nem
sempre é clara, se compararmos ocorrências de dados semanticamente iguais” (MELLO et
al, 2000).
Sistemas de bases de dados relacionais têm-se apresentado como uma das
abordagens mais utilizadas atualmente para o armazenamento de dados XML. São sistemas
maduros, apresentam uma boa escalabilidade, são encontrados muitos produtos comerciais
disponíveis, é uma tecnologia bastante conhecida, além do uso de SQL com processadores
de consultas bem otimizados.
“SQL é a linguagem padrão para se lidar com bancos de dados relacionais, e é
aceita por quase todos os produtos existentes no mercado” (DATE, 2000).
As operações básicas realizadas por SQL são:
• INSERT: permite inserir dados em tabelas da base de dados
21
o Exemplo: INSERT INTO <tabela> [<campos>] [VALUES
<valores>]
• UPDATE: permite atualizar dados em tabelas da base de dados
o Exemplo: UPDATE <tabela> SET <campo> =
<expressão> [WHERE <condição>]
• DELETE: permite deletar dados em tabelas da base de dados;
o Exemplo: DELETE FROM <tabela> [WHERE <condição>]
• SELECT: permite selecionar dados em tabelas da base de dados.
o Exemplo: SELECT * FROM [<nome da tabela>] WHERE
[<condição>]
Para utilizar sistemas de bases de dados relacionais para o armazenamento de
XML, tem se a necessidade de fazer o mapeamento de dados XML para o modelo de dados
relacional. No tópico 2.6 serão apresentadas algumas abordagens sobre esses
mapeamentos.
A seguir, são apresentados três SGBDs e algumas funcionalidades para o
armazenamento de XML.
2.5.1 DB2
O DB2 é um SGBD relacional desenvolvido pela IBM (DB2 2003a). A partir da
segunda versão passou a suportar o armazenamento e manipulação de objetos complexos,
acoplando as características comuns do DB2 Universal Database (DB2 UDB) à
extensibilidade da XML (DB2 2003b).
Para trabalhar com XML, utiliza-se o DB2 XML Extender. Essa ferramenta permite
trabalhar com dois meios de armazenamento de documentos XML (DB2 2003a). O
primeiro é armazenar o documento XML inteiro, sem modificações, em uma coluna da
base de dados (XML column). O segundo permite fazer uma decomposição do documento
XML, armazenando os dados extraídos em tabelas relacionais (XML collection).
Abaixo são apresentados algumas das funcionalidades oferecidas pelo DB2 XML
Extender (DB2 2003c):
• Armazenamento, recuperação e atualizações dos dados XML em uma única
coluna;
22
• Facilita o levantamento de informações para soluções de business-to-
business e e-business através de formato XML-based;
• Extração de elementos e atributos em tipos de dados tradicionais SQL,
(sistema de indexação e funcionalidades de SQL query para DB2);
• Armazena documentos XML como uma coleção de dados DB2, em
múltiplas colunas e em tabelas.
2.5.2 SQL Server 2000
É um produto da Microsoft que trabalha com modelo de dados relacional e suporta
aplicações Cliente/Servidor. A partir do SQL Server 2000, a Microsoft disponibilizou
suporte para trabalhar com XML, permitindo importar e exportar dados XML, formas de
adaptação entre dados XML e dados relacionais etc (SERVER 2000b).
As principais funções de manipulação oferecidas pelo SQL Server 2000 para
trabalhar com dados XML (SERVER 2000a) são:
• OpenXML: fornece visões relacionais de dados XML; podem ser usadas
para consultas a dados XML e junção de dados XML com tabelas
relacionais existentes;
• FOR XML: fornece acesso a dados XML existentes em uma base de dados
relacional, com a utilização de SELECT e de palavras-chaves de OPenXML
T/SQL.
Com o SQL Server 2000, os usuários podem realizar consultas e retornar o
resultado em formato XML, fazer combinações de dados de tabelas relacionais com dados
originados de documentos XML, mapear múltiplas tabelas em uma junção com atributos e
elementos específicos de documentos XML etc (SERVER 2000a).
2.5.3 Oracle 9i
O Oracle é um SGBD relacional desenvolvido pela Oracle Corporation. Suporta
três tipos de armazenamento de documentos XML (ORACLE 2002):
• Tipo de dados Char: é um campo string. Nesse caso, os dados são
armazenados em uma tabela do banco de dados como uma única cadeia de
23
caracteres. Uma das maiores dificuldades na utilização desse tipo de
armazenamento é a lentidão no processamento de consultas aos dados, pois
o conteúdo dos dados pode ser muito extenso;
• Tipo de dados CLOB: nesse tipo de armazenamento, o documento XML
fica armazenado em um grande arquivo texto na base de dados e há um
ponteiro no campo da tabela para esse documento. Uma das maiores
dificuldades de se trabalhar com esse tipo de dados é que o documento só
pode ser recuperado por completo;
• Tipo de dados XMLType: esse tipo de dados armazena o documento XML
como é feito com o tipo CLOB, mas com o auxílio de métodos que vêm
acoplados a ele permite criar, extrair e indexar os dados contidos no
documento e recuperar tags específicas com a utilização de XPath. Algumas
funções do XMLType: CreateXML(); ExistsNode(); Extract() etc.
2.6 Geração de esquema lógico relacional a partir de DTD
DTDs são utilizadas como esquemas para documentos XML. Através de DTDs,
pode-se prever o que existirá em um documento XML e o que o documento pode conter,
com a definição de elementos e atributos ligados aos elementos.
Há na literatura várias abordagens para o mapeamento de uma DTD para um
esquema lógico relacional. Algumas destas abordagens são apresentadas a seguir.
2.6.1 Primeira abordagem
A primeira destas abordagens é definida da seguinte forma (BOU 2001):
• Para cada elemento complexo, cria-se uma tabela e uma coluna de chave
primária;
• Para cada elemento com conteúdo misto, cria-se uma tabela separada para
armazenar o PCDATA, ligando à tabela pai através da chave primária da
tabela pai;
• Para cada atributo monovalorado de um elemento e para cada elemento
filho simples de ocorrência única, cria-se uma coluna na tabela do elemento.
24
Se o elemento ou atributo do elemento for opcional, a coluna também é
opcional;
• Para cada atributo multivalorado e para cada elemento filho simples de
múltipla ocorrência, cria-se uma tabela separada para armazenar os valores,
ligada à tabela pai através da chave primária da tabela pai;
• Para cada elemento filho complexo, liga-se a tabela do elemento pai à tabela
do elemento filho com a chave primária da tabela pai.
Na figura 4 têm-se o exemplo do funcionamento desse processo. Para esse exemplo
têm-se a DTD da figura 3:
<!ELEMENT artigo(autor,titulo_artigo,resumo,secao*,bibliografia)><!ELEMENT autor (nome,instituicao?,endereco?)><!ELEMENT nome (#PCDATA)><!ELEMENT instituicao (#PCDATA)><!ELEMENT endereco (#PCDATA)><!ELEMENT secao (paragrafo|figura)+><!ELEMENT paragrafo (#PCDATA)><!ELEMENT figura EMPTY><!ATTLIST figura tipo NOTATION (gif|jpg) "gif"
nome CDATA "figura1"><!ATTLIST artigo data CDATA #REQUIRED
ultima_revisao CDATA #REQUIREDversao CDATA #IMPLIED>
<!ATTLIST secao titulo CDATA #REQUIREDnumero ID #REQUIRED>
<!ELEMENT bibliografia (referencia+)><!ELEMENT referencia (obra,autor+,ano?,local?)><!ATTLIST referencia id ID #REQUIRED><!ELEMENT obra (#PCDATA)><!ELEMENT ano (#PCDATA)><!ELEMENT local (#PCDATA)><!ELEMENT titulo_artigo (#PCDATA)><!ELEMENT resumo (#PCDATA|paragrafo)*>
Figura 3 – DTD exemplo para as abordagens de mapeamento.
Seguindo os passos citados anteriormente, têm-se o seguinte esquema lógico
relacional da figura 4.
25
Tb_artigo(id,id_autor,titulo_artigo,id_resumo,id_bibliografia,data,ultima_revisao,versao)Tb_autor(id,nome,instituicao,endereco)Tb_resumo(id)Tb_pcdata(id,id_resumo,pcdata)Tb_paragrafo_resumo(id,id_resumo,paragrafo)Tb_secao_artigo(id_artigo,id_secao)Tb_secao(id,numero)Tb_paragrafo(id,paragrafo)Tb_paragrafo_secao(id_paragrafo,id_secao)Tb_figura(id,tipo,nome)Tb_figura_secao(id_figura,id_secao)Tb_bibliografia(id)Tb_referencia(id,id_bibliografia,obra,ano,local)Tb_autor_referencia(id_autor,id_referencia)
Figura 4 – Esquema lógico relacional gerado segundo a DTD da figura 3 (abordagem 1)
Notação: na representação do modelo relacional as chaves primárias estão definidas
em negrito e sublinhadas; as chaves primárias e estrangeiras estão em negrito, sublinhadas
e em itálico; as chaves estrangeiras estão em itálico.
2.6.2 Segunda abordagem
Um dos problemas em se mapear DTDs para esquemas lógicos relacionais é a
grande fragmentação do documento, como pode ser visto no exemplo anterior. A segunda
abordagem visa diminuir essa fragmentação. Abaixo, têm-se os principais pontos que são
tratados na segunda (SHA 99):
• A complexidade permitida na declaração de elementos, a cardinalidade dos
elementos (opcional, obrigatório e multivalorado), elemento filho, elemento
raiz etc;
• Os conflitos de mapeamento entre o esquema relacional (atributos e tabelas)
e o aninhamento arbitrário de elementos na DTD;
• Os atributos multivalorados e a recursão entre elementos.
Abaixo seguem as transformações necessárias para tratar os pontos citados acima
(SHA 99):
1. Transformações de nivelamento: converter uma definição aninhada em uma
representação plana. Por exemplo:
� (a,b)* é transformado em a*,b*
26
� (a,b)? é transformado em a?,b?
� (a|b) é transformado em a?,b?
2. Transformações de simplificação: reduzir vários operadores unários em um
único. Por exemplo:
� a** é transformado em a*
� a*? é transformado em a*
� a?* é transformado em a*
� a?? é transformado em a?
3. Transformações de agrupamentos: agrupar sub-elementos que possuem o
mesmo nome. Por exemplo:
� ...,a*,...,a*,... é transformado em a*,...
� ...,a*,...,a?,... é transformado em a*,...
� ...,a?,...,a*,... é transformado em a*,...
� ...,a?,...,a?,... é transformado em a*,...
� ...,a,...,a,... é transformado em a*,...
4. Transformação de operadores + em *;
Um elemento definido como (SACCOL 2001):
<!ELEMENT a ((b|c|e)?(e?|(f?,(b,b)*))*)>
é transformado em: <!ELEMENT a (b*,c?,e*,f*)>.
Após a simplificação da DTD, gera-se um grafo simplificado, o qual servirá como
base para gerar o modelo lógico relacional. Abaixo têm-se um exemplo de um grafo.
Figura 5 – Grafo da DTD da figura 3 (segunda abordagem)
27
Cria-se tabelas para todos os elementos da DTD que não possuem nó apontando
para ele (artigo). Elementos que são apontados por mais de um nó geram tabelas
quando são recursivos. Todos os elementos apontados por * geram tabelas separadas.
“Elementos apontados por um único nó são agrupados nas tabelas já existentes. Na
existência de elementos mutuamente recursivos e alcançáveis por um único nó, um deles
deve gerar uma tabela separada. Os outros elementos existentes devem ser agrupados nas
tabelas existentes” (SACCOL 2001).
Abaixo têm-se o esquema lógico relacional da DTD da figura 3 gerado a partir da
abordagem citada acima.
Tb_artigo(id,nome,instituicao,endereco,ultima_revisao,data,versoa,titulo_artigo,id_resumo,id_bibliografia)Tb_resumo(id)Tb_pcdata(id,id_resumo,pcdata)Tb_paragrafo(id,paragrafo)Tb_resumo_paragrafo(id_resumo,id_paragrafo)Tb_secao(id,id_artigo,numero)Tb_secao_paragrafo(id_secao,id_paragrafo)Tb_figura(id,id_secao,tipo,nome)Tb_bibliografia(id)Tb_referencia(id,id_bibliografia,local,ano,obra)Tb_autor(id,id_referencia,nome,instituicao,endereco)
Figura 6 – Esquema lógico relacional gerado segundo a DTD da figura 3 (abordagem 2).
2.6.3 Terceira abordagem
Segundo (LU et al 2003): Elementos XML e atributos são modelados como
elementos. Uma DTD D é modelada como um conjunto de elementos XML {d1, d2,
..., dk}. Cada elemento XML di (i=1, ..., k) é da forma ni=ei, onde ni é o
nome do elemento XML e ei é a expressão da DTD.
Cada expressão da DTD é composta de nomes de elementos XML (expressões
primitivas) e outras subexpressões DTD com os seguintes operadores: , * + ? |
Uma expressão DTD e é definida recursivamente na seguinte notação BNF, onde n
varia sobre os nomes de elementos XML e e1, ..., em sobre as expressões DTD.
Essa abordagem contém três etapas, que são (LU et al 2003):
• Eliminação da complexidade das DTDs;
28
• Criação e inlining de grafos DTD;
• Geração de um esquema relacional.
A figura 6 mostra as regras utilizadas para eliminar a complexidade das DTDs.
1.e+�e*2.e?�e3.(e1|···|en)�(e1,···,en)4.(a)(e1,···,en)*�(e1*,···,en*)
(b) e**�e*5.(a) ···,e, ···,e, ···�···,e*,···,···
(b) ···,e, ···,e*,···�···,e*,···,···(c) ···,e*,···,e,···�···,e*,···,···(d) ···,e*,···,e*,···�···,e*,···,···
Figura 7 – Regras para eliminar a complexidade dos DTDs (LU et al 2003).
Regra 1. Aplicando a regra 1 o DTD resutante não conterá +.
Regra 2. Aplicando a regra 2 o DTD resultante não conterá ?.
Regra 3. Aplicando a regra 3 o DTD resultante não conterá |.
Regra 4(a) e 4(b). Aplicando as regras 4 (a) e 4(b) o DTD resultante fica
da seguinte forma: (e1,e2,...,en). Cada ei =e ou e* (i=1,...,n), onde e é o
nome do elemento.
Regra 5(a), 5(b), 5(c) e 5(d). Aplicando essas regras o DTD resultante
fica da seguinte forma: (e1,e2,...,en). Sendo que, cada ei contém um nome distinto
do elemento.
Aplicando as regras citadas acima nesse DTD (LU et al 2003): <ELEMENT a
((b+,c*,d?)?,(e?,f,(g*,h?)+)?)> o seu DTD resultante é: <ELEMENT a
(b*,c*,d,e,f,g*,h*)>.
Segundo (LU et al 2003) as regras para eliminar a complexidade dos DTDs
apresentadas acima sofreram algumas melhorias em relação às regras apresentadas por
(SHA 99):
• Completude: Considera todas as combinações possíveis dos operadores e
elementos XML. Como por exemplo, (e1|···|en)?. Essa condição não é
tratada por (SHA 99);
• Eficiência: O algoritmo garante que as regras sejam aplicadas de acordo
com a ordem apresentada na figura 7, reduzindo o número de regras a serem
29
aplicadas a cada passo;
• Simplificação extra: Eliminar o “?” simplifica o grafo resultante da DTD.
Na etapa de criação e inlining do grafo da DTD, cria-se o grafo correspondente à
DTD simplificada. No grafo, cada nó representa um elemento de XML e cada arco
representa um operador de “,” ou “*”. O procedimento inlining considera três casos
(LU et al 2003):
• Caso 1: O elemento a é conectado a b por a, e b não tem nenhum outro
arco chegando a ele. Em outras palavras b não é um nó compartilhado;
• Caso 2: O elemento a é conectado a b por a, mas b contém outros arcos
chegando a ele. Ou seja b é um nó compartilhado;
• Case 3: O elemento a é conectado a b por a. Nesse caso, cada a contém
ocorrências múltiplas do elemento b.
Abaixo têm-se o algoritmo apresentado por (LU et al 2003):
Algorithm Inline(DTDGraph G)Begin
For each node e in G doIf not visited(e)then
InlineNode(e)End If
End ForEndAlgorithm InlineNode(Node e)Begin
Mark e as “visited”For each child c of e do
If not visited(c)thenInlineNode(c)
End IfEnd ForFor each child c of e do
If inlinable(c)thene.inlinedSet ∪=c.inlinedSet;assign all children of c as thechildrenof eAndthendeletecfromG
End IfEnd For
End
Figura 8 – Algoritmo inlining (LU et al 2003)
O algoritmo inlining pode ser executado em O(n) onde n é o número dos elementos
30
na DTD da entrada.
Abaixo são mostrados os grafos inlining da DTD (LU et al 2003):
Figura 9 – Gráfico inlining da DTD (LU et al 2003)
Usando o procedimento inlining da figura 8, o grafo da DTD mostrado na figura
9.A será inlined no grafo mostrado na figura 9.B, e o grafo da DTD mostrado na figura 9.C
será inlined no grafo mostrado na figura 9.D.
Após aplicar o algoritmo, observa-se que um grafo da DTD tem as seguintes
propriedades: os nós são conectados por um arco ‘,’ ou ‘*’ e um arco ‘,’ deve apontar para
um nó compartilhado (LU et al 2003). Abaixo tem se o grafo inlining da DTD da figura 3.
Figura 10 – Grafo inlining da DTD da figura 3
31
Depois do grafo simplificado da DTD, a última etapa é gerar um esquema
relacional baseado neste grafo. O esquema relacional gerado suporta operações como
insert, select, delete e update de um elemento arbitrário de XML declarado na entrada da
DTD (LU et al 2003).
Gerando o esquema lógico relacional (LU et al 2003):
1. Para cada nó e uma relação e é gerada com os seguintes atributos
relacionais.
o O ID é a chave primária, e para cada atributo XML A de e, um
atributo relacional correspondente ao atributo A é criado com o
mesmo nome;
o If | e.inilinedSet | >=2, introduz-se o nodetype do
atributo para indicar o tipo do elemento XML a ser armazenado em
uma tupla;
o O nome de todo elemento XML terminal em e.inilinedSet.
Uma vez que um elemento não terminal é armazenado com valores
de ID e nodetype, e o armazenamento de sub-elementos contidos
nele, nenhum atributo adicional é necessário;
o Se houver um arco de e para o nó c, introduz-se c.ID como uma
chave estrangeira em e referenciando a relação c.
2. Se houver ao menos duas relações t1(ID) e t2(ID) geradas pelo item
1, então combina-se todas as relações da forma t(ID) em uma única
relação table1(ID,nodetype), sendo que o nodetype indica qual
elemento XML é armazenado em uma tupla;
3. Se houver ao menos duas relações t1(ID,t1) e t2(ID,t2) geradas
no item 1, então combina-se toda as relações da forma t(ID,t) em uma
única relação table2(ID,nodetype,pcdata), sendo que o
nodetype indica qual elemento XML é armazenado em uma tupla;
4. Se houver ao menos um arco * no grafo inlined da DTD, introduz-se uma
relação edge(parentID,childID,parentType,childType)
para armazenar todos os relacionamentos parent-child
32
correspondentes a arcos *.
Aplicando esta abordagem à DTD da figura 3, têm-se o seguinte esquema gerado:
Tb_artigo(id,id_autor,ultima_revisao,data,versao,id_resumo,id_bibliografia)Tb_autor(id,nome_autor,instituicao,endereco)Tb_resumo(id)Tb_pcdata(id,id_resumo,pcdata)Tb_paragrafo(id,paragrafo)Tb_resumo_paragrafo(id_resumo,id_paragrafo)Tb_secao(id,id_artigo,numero)Tb_secao_paragrafo(id_secao,id_paragrafo)Tb_figura(id,tipo,nome)Tb_secao_figura(id_secao,id_figura)Tb_bibliografia(id)Tb_referencia(id,id_bibliografia,local,ano,obra)Tb_referencai_autor(id_referencia,id_autor)
Figura 11 – Esquema lógico relacional gerado segundo a DTD da figura 3 (abordagem 3)
2.6.4 Quarta abordagem
A abordagem proposta por (FLO 99) define um esquema relacional a partir de um
grafo resultante de um documento XML. Neste grafo, nos modelam objetos, arcos
modelam atributos do objeto (rótulos) e folhas contém valores de dados (cadeias de
caracteres).
Essa abordagem é dividida em duas categorias: mapeamento de atributos e
mapeamento de valores.
O mapeamento de atributos pode ser feito de 4 formas distintas: armazenar todos os
atributos em uma única tabela (abordagem dos arcos); agrupar todos os atributos com o
mesmo nome em uma mesma tabela (abordagem dos atributos); armazenar todos os
atributos em uma mesma tabela, mas com nomes de colunas diferentes para cada atributo
(tabela universal); armazenar atributos multivalorados em tabelas separadas (abordagem
universal normalizada).
A figura 12 mostra um documento XML válido segundo a DTD da figura 3
33
<?xml version='1.0'?><!DOCTYPE artigo SYSTEM "artigo.dtd"><artigo ultima_revisao="2001" data="10/02/2001">
<autor><nome>D`ilton</nome>
</autor><titulo_artigo>XML</titulo_artigo><resumo>
resumo 1<paragrafo>Paragrafo 1</paragrafo>
</resumo><bibliografia>
<referencia id="ref1"><obra>obra 1</obra><autor>
<nome>D`ilton</nome></autor>
</referencia></bibliografia>
</artigo>
Figura 12 – Documento XML válido segundo a DTD da figura 3
A figura 13 mostra e representação em forma de grafo do documento XML da
figura 12.
Figura 13 – Grafo do documento XML da figura 12
Com base no grafo da figura 13, têm-se abaixo a tabela gerada seguindo o
mapeamento de atributos – abordagem dos arcos.
34
Tabela 1 – Exemplo tabela baseado em arco – com base no grafo da figura 13 Origem Ordem Nome Destino
R 1 artigo 1
1 1 ultima_revissao 2001
1 2 data 10/20/2001
1 3 autor 2
2 1 nome D`ilton
O mapeamento de valores pode ser feito de duas formas (FLO 99): tabelas
separadas de valores (uma tabela para cada tipo de dados) e mapeamento Inlining (valores
e atributos nas mesmas tabelas).
Na tabela 2 têm-se uma representação do mapeamento Inlining, tendo como base o
grafo da figura 13.
Tabela 2 – Tautor – mapeamento com Inlining Tautor
Origem Ordem Val_int Val_string Destino
1 3 Null Null 2
Tabela 3 – Tnome – mapeamento com Inlining
Tnome
Origem Ordem Val_int Val_string Destino
2 1 Null D`ilton null
Maiores detalhes destas abordagens podem ser encontradas em (FLO 99).
35
3. MATERIAIS E MÉTODOS
O trabalho foi desenvolvido no Laboratório de Multimídia (LABMIDIA) do
CEULP/ULBRA – Palmas – TO.
A ferramenta de desenvolvimento utilizada foi o Delphi 7. Foi utilizado também o
compilador javacc e o j2sdk para a utilização do DTDParser.jj (Parser utilizado para gerar
a representação da DTD em XML).
Seguiu-se a seguinte metodologia: primeiro definiu-se uma DTD para validar os
documentos XML gerados pelo DTDParser. A partir desta DTD, utilizou-se o componente
XML Data Binding (Delphi) para gerar uma interface que acessa os documento XML
gerados pelo DTDParser. Em seguida, foi implementado o algoritmo proposto nesse
trabalho, o qual gera um script.sql, sendo que esse script é a representação da DTD em um
modelo relacional.
36
4. RESULTADOS E DISCUSSÕES
Este capítulo apresenta a proposta para o mapeamento de DTDs para um modelo
lógico relacional. Também são mostrados o estudo de caso utilizado, a representação da
DTD em formato XML e o algoritmo proposto para o mapeamento.
No tópico abaixo têm-se a proposta de desenvolvimento desse trabalho.
4.1 Proposta
Esse trabalho visa desenvolver um algoritmo para o mapeamento de DTDs para um
modelo lógico relacional e também a sua implementação. Primeiramente, será feita uma
representação da DTD em um formato XML através de um Parser javacc. Após, será
realizado o mapeamento da DTD através do aplicativo que gerará um script.sql com o
modelo lógico relacional da DTD para o SQL Sever. Para entender melhor a proposta desse
trabalho é apresentada na figura 14 a arquitetura do sistema proposto.
Figura 14 – Arquitetura do Sistema
37
A arquitetura do sistema está dividida da seguinte forma:
1. DTD.dtd: entra-se no sistema com uma DTD válida;
2. JavaCC: nesse módulo do sistema utiliza-se de um parser, gerado por uma
gramática com ações semánticas DTDparser.jj, que valida uma DTD
(JAVACC 2003). Esse DTDparser.jj foi modificado de forma a gerar uma
representação XML de uma DTD;
3. DTD.XML: é o documento XML gerado pelo parser do módulo JavaCC, o
qual será utilizado para gerar os script.sql através do aplicativo;
4. XML Data Binding (Delphi): este é um componente do Delphi que
a partir de uma DTD gera uma interface que permite acessar qualquer
documento XML válido segundo esta DTD. Essa interface é utilizada para
fazer a leitura do DTD.XML, possibilitando a implementação do algoritmo
proposto neste trabalho;
5. script.sql: modelo lógico relacional gerado com a utilização do
algoritmo proposto nesse trabalho;
6. SGBD SQL Server: SGBD utilizado para executar os comandos SQL de
criação de tabelas.
4.2 Estudo de caso
DTDs são utilizadas para definir uma estrutura para documentos XML. Nessa
seção, têm-se exemplos de utilização de DTD e de documentos XML válidos segundo uma
DTD. A DTD utilizada para o exemplo tem sua definição voltada para publicações de
artigos e livros. Um artigo pode ter um título, autor, bibliografia etc. Um
livro pode ter um título, autores, bibliografia, capítulo, seção etc. A
próxima figura mostra a DTD definida para publicações.
38
<!ELEMENT publicacoes (livro|artigo)+><!ELEMENT livro(titulo,(autores|autor),editora?,capitulos?,secao*,bibliografia?)><!ATTLIST livro data CDATA #IMPLIED
ultima_revisao CDATA #IMPLIEDversao CDATA #IMPLIED cod ID #REQUIREDedicao CDATA #IMPLIED >
<!ELEMENT autores (autor*)><!ELEMENT autor (#PCDATA|nome)*><!ELEMENT nome (#PCDATA)><!ELEMENT editora (#PCDATA)><!ELEMENT capitulos (capitulo+)><!ELEMENT capitulo (#PCDATA | referencia | paragrafo)*><!ATTLIST capitulo titulo CDATA #REQUIRED
numero ID #REQUIRED ><!ELEMENT referencia EMPTY><!ATTLIST referencia cod IDREF #REQUIRED ><!ELEMENT paragrafo (#PCDATA | referencia)*><!ELEMENT secao (paragrafo | figura)+><!ATTLIST secao titulo CDATA #REQUIRED
numero (s1 | s3) #REQUIRED ><!ELEMENT bibliografia (ref+)><!ELEMENT ref (obra, autor)><!ATTLIST ref id ID #REQUIRED ><!ELEMENT obra (#PCDATA)><!ELEMENT figura EMPTY><!ATTLIST figura tipo CDATA #REQUIRED
nome (figura1.gif | figura2.gif) #REQUIRED ><!ELEMENT artigo (titulo,autor+,bibliografia?)><!ELEMENT titulo (#PCDATA)>
Figura 15 – DTD para publicações de livros e artigos
Para a DTD da figura 15 foram definidos três documentos XML. Na figura 16 têm-
se o primeiro documento XML válido segundo a DTD da figura 15.
39
<?xml version="1.0"?><!DOCTYPE publicacoes SYSTEM "publicacoes.dtd"><publicacoes>
<livro data="05/09/2000" ultima_revisao="10/01/2001"cod="l1"><titulo>XML</titulo><autor>D`ilton</autor><editora>Ciência Moderna</editora><capitulos>
<capitulo titulo="Introducao" numero="n1">Texto teste...<paragrafo>Paragrafo teste 1</paragrafo>
</capitulo></capitulos><bibliografia>
<ref id="f1"><obra>XML</obra><autor>
<nome>Deise</nome></autor>
</ref></bibliografia>
</livro></publicacoes>
Figura 16 – Documento XML válido segundo a DTD da figura 15 – exemplo 01
Para esse primeiro documento XML (figura 16) foi armazenado somente um
livro, o qual está composto por titulo, autor, editora, capitulos e
paragrafo. A figura 17 mostra o segundo documento XML válido conforme a DTD da
figura 15.
40
<?xml version="1.0"?><!DOCTYPE publicacoes SYSTEM "publicacoes.dtd"><publicacoes>
<artigo><titulo>IonoSoft</titulo><autor>
<nome>D`ilton</nome><nome>Washington Luiz Carvalho Lima</nome>Piveta
</autor><bibliografia>
<ref id="f3"><obra>Ionosfera</obra><autor>
<nome>Washington</nome></autor>
</ref></bibliografia>
</artigo><livro data="05/09/2000" ultima_revisao="10/01/2001"cod="l1">
<titulo>XML</titulo><autor>D`ilton</autor><editora>Ceiencia Moderna</editora><capitulos>
<capitulo titulo="Introducao" numero="n1">Texto teste...<paragrafo>Paragrafo teste 1</paragrafo>
</capitulo></capitulos><bibliografia>
<ref id="f1"><obra>XML</obra><autor>
<nome>Deise</nome></autor>
</ref></bibliografia>
</livro></publicacoes>
Figura 17 – Documento XML válido segundo a DTD da figura 15 – exemplo 02
O documento XML da figura 17 possui um artigo e um livro, sendo composto por
titulo, autor e bibliografia. O livro possui titulo, autor, editora,
capitulos e paragrafo. Como pode ser visto, os documentos da figura 16 e 17 são
válidos segundo a mesma DTD e possuem estruturas diferentes. A figura 18 mostra outro
exemplo de um documento XML válido segundo a DTD da figura 15.
41
<?xml version="1.0"?><!DOCTYPE publicacoes SYSTEM "publicacoes.dtd"><publicacoes>
<artigo><titulo>IonoSoft</titulo><autor>
<nome>D`ilton</nome><nome>Washington Luiz Carvalho Lima</nome>Piveta
</autor><bibliografia>
<ref id="f3"><obra>Ionosfera</obra><autor>
<nome>Washington</nome></autor>
</ref></bibliografia>
</artigo><livro data="05/09/2000" ultima_revisao="10/01/2001"cod="l1">
<titulo>XML</titulo><autor>D`ilton</autor><editora>Ceiencia Moderna</editora><capitulos>
<capitulo titulo="Introducao" numero="n1">Texto teste...<paragrafo>Paragrafo teste 1</paragrafo>
</capitulo></capitulos><bibliografia>
<ref id="f1"><obra>XML</obra><autor>
<nome>Deise</nome></autor>
</ref></bibliografia>
</livro><artigo>
<titulo>Mapeamento de DTDS</titulo><autor>D`ilton</autor><bibliografia>
<ref id="f1"><obra>DataBase DTDs</obra><autor>
<nome>D`ilton</nome></autor>
</ref></bibliografia>
</artigo></publicacoes>
Figura 18 – Documento XML válido segundo a DTD da figura 15 – exemplo 03
42
Para validar os documentos XML da figura 16, 17 e 18 foi utilizada a mesma DTD.
Como pode ser visto, todos os documentos possuem estruturas diferentes, sendo que estas
estruturas estão previstas na DTD. Ao se mapear essa DTD para um modelo lógico
relacional, deve-se levar em conta a cardinalidade dos elementos, flexibilidade do
documento, atributos e garantir que todos os dados sejam representados no modelo lógico
relacional.
4.3 Representação da DTD em formato XML
Para facilitar o mapeamento da DTD para um modelo lógico relacional, essa DTD
será representada em formato XML, através de um analisador sintático e léxico.
O analisador léxico (AHO et al, 1995) tem como função principal ler os caracteres
de entrada e produzir uma seqüência de tokens que o parser utiliza para a análise sintática.
O analisador sintático (AHO et al,1995) “obtém uma cadeia de tokens proveniente
do analisador léxico, e verifica se ela pode ser gerada pela gramática da linguagem-fonte”.
O analisador sintático relata todos os erros de sintaxe, como por exemplo (AHO et
al,1995):
• Léxicos: grafia errada de um identificador, palavras-chaves ou operador;
• Sintático: uma expressão aritmética com parênteses não-balanceados;
• Semânticos: um operador aplicado a um operando incompatível;
• Lógicos: uma chamada infinitamente recursiva.
Um exemplo de um analisador sintático e léxico é o Java Compiler-Compiler
(JavaCC) (JAVACC 2000). Para mapear a DTD para um formato XML será utilizado um
parser DTDParser (DTDParser 2001) compilado pelo JavaCC. Esse parser recebe em sua
entrada uma DTD e após, validá-la, gera em sua saída um documento XML representando
a DTD. Segue em anexo o DTDParser.
Para melhor entender a representação de uma DTD em um formato XML será
apresentada na figura 19 uma DTD e na figura 20 a sua representação em XML.
<!ELEMENT msg (de,para*,conteudo)><!ELEMENT de (#PCDATA)><!ELEMENT para (#PCDATA)><!ELEMENT conteudo (#PCDATA)>
Figura 19 – DTD msg O DTDParser faz um mapeamento de todos os elementos, atributos, cardinalidades,
43
montando um documento XML como o mostrado na figura 20.
<dtd><elemento>
<pai><filho><nome>de</nome></filho><filho><nome>para</nome></filho><filho><nome>conteudo</nome></filho><nome>msg</nome>
</pai></elemento><elemento>
<pai><pcdata>PCDATA</pcdata><nome>de</nome>
</pai></elemento><elemento>
<pai><pcdata>PCDATA</pcdata><nome>para</nome>
</pai></elemento><elemento>
<pai><pcdata>PCDATA</pcdata><nome>conteudo</nome>
</pai></elemento>
</dtd>
Figura 20 – Representação XML da DTD da figura 19
A figura 20 mostra a representação XML da DTD da figura 19. O documento XML
tem como elemento raiz <DTD> e para armazenar o elemento raiz e seus filhos definidos
na DTD têm-se a tag <Elemento> e dentro da mesma tem a tag <pai> e dentro dela
zero ou várias tags <filho> com seu respectivo nome, zero ou uma tag <pcdata> e a
tag <nome>, que é o nome do elemento raiz.
No próximo tópico têm-se a apresentação do algoritmo desenvolvido nesse
trabalho.
4.4 Algoritmo de geração de esquemas lógicos a partir da DTD
Nessa seção será apresentado o algoritmo desenvolvido nesse trabalho. Para
44
melhor compreensão do algoritmo, ele será divido por tipos de elementos como:
elemento PCDATA, elemento complexo, elemento vazio e elemento
misto. A figura 19 mostra o início do algoritmo.
iniciopara cada elemento da DTD{
se o elemento for raiz{gera uma tabela;cria um coluna chave primaria para esta tabela;se possui atributos{
addAtributosElemento(pai);}para cada filho do elemento{...}
}}
Figura 21 – Inicio do algoritmo
Como mostra a figura 21, primeiramente verifica-se o elemento raiz da DTD e cria-
se uma tabela com uma chave primária para esse elemento. Após, verifica-se se o mesmo
possui atributos; sendo verdade, adiciona-se os tributos do elemento em sua tabela através
do procedure addAtributosElemento(filho). Em seguida, verifica-se todos
os seus elementos filhos. Nas próximas seções têm-se um comentário sobre cada tipo de
elemento filho descrevendo, o seu mapeamento para o modelo relacional.
4.4.1 Elementos PCDATA
Para elemento PCDATA são consideradas duas categorias: os elementos
monovalorados (para esses elementos são considerados os elementos que podem
existir ou não no documento XML) e os elementos multivalorados.
No primeiro caso, os elementos são mapeados para a tabela do pai, caso não possua
atributos. Possuindo atributos e somente um pai, é armazenado na tabela do pai juntamente
com seus atributos. Possuindo atributos e mais de um pai, gera-se uma tabela para o
elemento com seus respectivos atributos e gera-se também uma tabela auxiliar
referenciando a tabela do pai e a tabela do filho.
Para o segundo caso, elementos multivalorados, gera-se uma tabela para o elemento
filho referenciando a tabela do pai, caso não possua atributos. Possuindo atributos e
somente um pai, gera-se uma tabela para o elemento com seus respectivos atributos e uma
45
referência à tabela do pai. Caso possua atributos e mais de um pai, gera-se uma tabela para
o filho com seus respectivos atributos e gera-se também uma tabela auxiliar referenciando
a tabela do elemento filho e a tabela de seu pai.
Na figura 22 é tratada a primeira abordagem.
se for PCDATA e monovalorado{senão possui atributos{
adiciona uma coluna para este elemento na tabela pai;}senão{
se possui somente um pai{adiciona uma coluna para este elemento na tabelapai;addAtributosElementoPcdata(pai,filho,modifier,cont_pai);
}senão{gera uma tabela para o filho com uma coluna chaveprimaria e uma coluna para o elemento filho;adiciona o id do filho na tabela pai;addAtributosElementoPcdata(pai,filho,modifier,cont_pai);}
}}
Figura 22 – Parte do algoritmo que trata de elemento PCDATA e monovalorado.
A figura 22 mostra o mapeamento de elemento PCDATA e monovalorado para
um modelo relacional. Primeiramente, verifica-se se o elemento possui atributos; caso o
elemento não possua atributos, cria-se uma coluna para o elemento na tabela pai, sendo que
também é levado em conta se o elemento é opcional ou obrigatório. Se o elemento possui
atributos são levadas em conta duas condições: verificar se o elemento possui somente um
pai ou mais de um pai.
Acontecendo do elemento possuir somente um pai, adiciona-se na tabela pai uma
coluna para o elemento filho, e através do procedure
addAtributosElementoPcdata(pai,filho,modifier,cont_pai)
adiciona-se os atributos do elemento filho na tabela pai.
O elemento, possuindo mais de um pai, é definido uma tabela para o filho, sendo
adicionado nessa tabela uma chave primária, uma coluna para o elemento e seus atributos
através do procedure
addAtributosElementoPcdata(pai,filho,modifier,cont_pai). Para as
duas condições acima é levado em conta se o elemento é obrigatório ou opcional.
46
A figura 23 descreve a segunda abordagem dessa seção.
se for PCDATA e multivalorado{senão possui atributos{
gera uma tabela com o nome do filho junto ao nome dopai, uma coluna chave estrangeira referenciando atabela do pai e uma coluna para o elemento filho;
}senão{se possui somente um pai{
gera uma tabela para o filho com uma coluna chaveprimaria, uma coluna chave estrangeirareferenciando a tabela do pai e uma coluna para oelemento filho;addAtributosElementoPcdata(pai,filho, ,modifier,cont_pai);
}senão{gera uma tabela para o filho com uma coluna chavePrimaria e uma coluna para o elemento filho;gera uma tabela auxiliar com duas colunas chavesestrangeiras, uma que referencia a tabela dofilhoe a outra a tabela pai;addAtributosElementoPcdata(pai,filho,modifier,cont_pai);}
}}
Figura 23 – Parte do algoritmo que trata de elemento PCDATA e multivalorado.
A figura 23 descreve o mapeamento de um elemento PCDATA e
Multivalorado para um modelo relacional. Como a abordagem anterior, verifica-se se
o elemento possui atributos; caso o elemento possua atributos, é gerada uma tabela com o
nome do filho junto ao nome do pai (tb_filho_pai) com suas respectivas colunas
(chave primária, chave estrangeira que referencia a tabela pai e uma coluna para o
elemento). Para os elementos que possuem atributos são levadas em conta duas condições:
a primeira, elementos que possuem somente um pai, e a segunda, elementos que possuem
mais de um pai.
Para a primeira condição, cria-se uma tabela para o filho com duas chaves (uma
primária e outra estrangeira referenciando a tabela pai), uma coluna para o elemento filho e
por fim adiciona à tabela os seus atributos. Na segunda condição, cria-se uma tabela para o
filho e uma tabela auxiliar que faz a ligação entre a tabela do filho e a tabela do pai. Na
próxima seção têm-se uma abordagem sobre o mapeamento de elementos
complexos para um modelo relacional.
47
4.4.2 Elemento complexo
Os elementos complexos foram divididos nas seguintes categorias:
• Elemento filho multivalorado e elemento pai
multivalorado. No caso de possuir somente um pai, gera-se uma tabela
para o filho com seus respectivos atributos, caso existam, e uma referência a
tabela do pai. Possuindo mais de um pai, gera-se uma tabela para o filho
com seus respectivos atributos, caso existam, e gera-se também uma tabela
auxiliar referenciando a tabela do filho e a tabela do pai;
• Elemento filho monovalorado e elemento pai
multivalorado. Faz-se o mesmo mapeamento da primeira categoria;
• Elemento filho multivalorado e elemento pai
monovalorado. Faz-se o mesmo mapeamento da primeira categoria;
• Elemento filho monovalorado e elemento pai
monovalorado. Nesse caso verifica-se se após o parêntese existe o
símbolo “*” ou “+”. Existindo esse símbolos e o elemento possuindo
somente um pai, gera-se uma tabela para o filho com seus atributos, caso
possua, e cria uma referência com a tabela do pai. Possuindo mais de um
pai, gera-se uma tabela para o filho com seus respectivos atributos e gera-se
também uma tabela auxiliar referenciando a tabela do pai. Ocorrendo de não
possuir os símbolos citados acima e também não possuindo somente filhos
multivalorados adiciona-se na tabela do pai uma referência à tabela do filho.
Caso possua somente filhos multivalorados, cria-se uma tabela para o pai
com seus respectivos atributos, caso os possua, e uma referência à tabela do
pai.
Para elemento filho multivalorado e elemento pai
multivalorado ou elemento filho monovalorado e elemento pai
multivalorado têm-se a figura 24.
48
se o (filho for multivalorado e pai multivalorado) ou (filho for
monovalorado e o pai multivalorado){se possui somente um pai{
gera uma tabela para o filho com uma coluna chaveprimaria e uma coluna chave estrangeira que referenciaa tabela pai;se possui atributos{addAtributosElemento(filho);}
}senão{gera uma tabela para o filho com uma coluna chaveprimaria;gera uma tabela auxiliar com duas colunas chavesestrangeiras, uma que referencia a tabela do filho eoutra a tabela do pai;se possui atributos{addAtributosElemento(filho);}
}}
Figura 24 – Parte do algoritmo que trata de elemento filho multivalorado e elemento pai multivalorado ou elemento filho monovalorado e elemento pai multivalorado.
A figura 24 mostra como é feito o mapeamento para essas duas situações. Para esse
mapeamento verifica-se duas condições: se o filho possui somente um pai e se o filho
possui mais de um pai.
Para a primeira condição é criada uma tabela para o filho, constituída de uma chave
primária, uma chave estrangeira referenciando a tabela pai; no caso de possuir atributos,
adiciona-se os atributos à tabela através do procedure
addAtributosElemento(filho). Na segunda condição, gera uma tabela para o
filho com uma coluna chave primária; possuindo atributos, adiciona-os na tabela. Cria-se
também uma tabela auxiliar que faz referência à tabela do filho e à tabela do pai.
A figura 25 descreve o mapeamento de elemento filho multivalorado e
elemento pai monovalorado.
49
se o filho for multivalorado e o pai monovalorado{se possui somente um pai{
gera uma tabela para o filho com uma coluna chaveprimaria e uma coluna chave estrangeira que referenciaa tabela pai;se possui atributos{addAtributosElemento(filho);}
}senão{gera uma tabela para o filho com uma coluna chaveprimaria;se possui atributos{addAtributosElemento(filho);}gera uma tabela auxiliar com duas coluna chavesestrangeiras uma que referencia o tabela filho e outraa tabela pai;} }
Figura 25 – Parte do algoritmo que trata de elemento filho multivalorado e
elemento pai monovalorado.
Para essa categoria são levadas em conta as mesmas condições das categorias
anteriores, como pode ser visto na figura 25.
A figura 26 descreve o mapeamento de elemento filho monovalorado e
elemento pai monovalorado.
se o filho for monovalorado e o pai monovalorado{se após o parêntese existir o símbolo “*” ou “+”{
se possui somente um pai{gera uma tabela para o filho com uma colunachave primaria e uma coluna chave estrangeiraque referencia a tabela pai;se possui atributos{addAtributosElemento(filho);}
}senão{gera uma tabela para o filho com uma colunachave primaria;se possui atributos{addAtributosElemento(filho);}gera uma tabela auxiliar com duas coluna chavesestrangeiras uma que referencia a tabela filho eoutra a tabela pai;
}senão{senão possuiSoFilhosMultivalorados(filho)
adiciona uma coluna chave estrangeira natabela pai;
senão{gera uma tabela para o filho com uma colunachave primaria e uma coluna chaveestrangeira que referencia a tabela pai;se possui atributos
addAtributosElemento(filho);}}}}
Figura 26 – Parte do algoritmo que trata de elemento filho monovalorado e elemento pai monovalorado.
50
Para fazer o mapeamento dessa categoria para um modelo relacional são levados
em conta duas situações: a primeira é se após o parêntese existe o símbolo “*” ou “+”
ex.: <!ELEMENT secao (paragrafo|figura|resumo|instituicao)+>; a
segunda é se não existe esses símbolos após o parêntese.
Na primeira situação verifica-se se o elemento possui somente um pai; essa
condição, sendo verdadeira, gera uma tabela para o filho com uma chave primária e uma
chave estrangeira referenciando a tabela pai e também verifica-se se o elemento possui
atributos e os adiciona na tabela filho. Caso o elemento filho possua mais de um filho, cria-
se uma tabela separada para o filho com os seus atributos, caso existam, e gera-se uma
tabela auxiliar que faz referência com a tabela do filho e a tabela do pai.
Para a segunda situação, são verificadas duas condições: se o elemento não possui
somente filhos multivalorados ex.: <!ELEMENT bibliografia (referencia+)>
e se o elemento só possui filhos multivalorados.
Para a primeira condição, simplesmente adiciona-se na tabela do pai uma coluna
chave estrangeira referenciando a tabela do filho, levando em conta se o elemento é
opcional ou obrigatório.
Na segunda condição gera-se uma tabela para o filho referenciando a tabela do pai;
caso possua atributos, eles são adicionados na tabela do filho. Na próxima seção têm-se
uma abordagem sobre o mapeamento de elemento vazio para um modelo relacional.
4.4.3 Elemento vazio
Para elemento vazio são levados em conta duas condições: elemento
monovalorado e elemento multivalorado. Para elemento monovalorado:
verifica-se se no pai do elemento existe um símbolo de “*” ou “+” após o parêntese, caso
exista, gera-se se uma tabela para o filho, com seus respectivos atributos e uma referência à
tabela do pai. Não existindo os símbolos, gera-se uma tabela para o filho, com seus
respectivos atributos, caso existam, e adiciona na tabela do pai uma coluna referenciando a
tabela do filho.
Elemento multivalorado: gera-se uma tabela para filho, com seus
respectivos atributos, caso existam, e uma tabela auxiliar relacionado com à tabela do filho
51
e à tabela do pai.
A figura 27 mostra o mapeamento desse tipo de elemento para um modelo
relacional.
se for vazio{se o filho for monovalorado{
verifica no pai se após o parêntese existe osímbolo “*” ou “+”{
gera uma tabela formada com o nome do pai e dofilho, com uma coluna chave primaria e uma chaveestrangeira que referencia a tabela pai;se possui atributos
addAtributosElemMisto(filho,pai);}senão{
gera uma tabela para o filho com uma colunachave primaria;se possui atributos
addAtributosElemento(filho);adiciona uma coluna chave estrangeira na tabelapai;}
}senão{gera uma tabela para o filho com uma colunachave primaria;se possui atributos
addAtributosElemento(filho);gera uma tabela auxiliar com duas colunas chavesestrangeiras uma que referencia a tabela dofilho e a outra a tabela do pai;}
}}
Figura 27 – Parte do algoritmo que trata de elemento vazio.
Para elemento vazio e elemento monovalorado existem duas situações:
elementos em que existe um símbolo de “*” ou “+” após o fechamento de parêntese de
seu pai (ex.: <!ELEMENT secao
(paragrafo|figura|resumo|instituicao)+> <!ELEMENT figura
EMPTY>); a segunda situação é quando isso não acontece.
Na primeira situação gera-se uma tabela, sendo que o nome da tabela será formado
pelo nome do filho junto ao nome do pai e essa tabela será composta por uma coluna chave
primária e uma coluna chave estrangeira referenciando a tabela pai; caso possua atributos,
eles são adicionado à tabela.
O elemento, estando na segunda situação, gera-se uma tabela para o filho com uma
coluna chave primária; caso possua atributos, eles são adicionados na tabela. Após,
52
adiciona-se na tabela do pai uma chave estrangeira que referencia a tabela do filho.
Para elemento vazio e elemento multivalorado cria-se uma tabela
para o filho com seus respectivos atributos, caso possua. Logo em seguida, gera-se uma
tabela auxiliar que referencia a tabela do pai e a tabela do filho.
Na próxima seção têm-se uma abordagem sobre o mapeamento de elemento
misto para um modelo relacional.
4.4.4 Elemento misto
O mapeamento de elemento misto para um modelo relacional é realizado da
seguinte forma: primeiramente, gera-se uma tabela em que o seu nome é composto pelo
nome do elemento filho e pelo nome do elemento pai. Caso possua atributos, eles são
adicionados à tabela através do procedure
addAtributosElemMisto(filho,pai); em seguida, percorre-se todos os filhos do
elemento, verificando as seguintes características: PCDATA, se o elemento filho
(filho do elemento misto) possui filhos, se o elemento filho é um PCDATA e se o
elemento filho é um elemento vazio.
Para PCDATA: o elemento possuindo somente um pai, gera-se uma tabela para o
PCDATA referenciando a tabela do pai; e caso possua mais de um pai, gera-se uma tabela
para o PCDATA e uma tabela auxiliar referenciando a tabela do PCDATA e a tabela do pai.
Quando elemento filho (filho do elemento misto) possui filhos: gera-se
uma tabela para o filho, com seus respectivos atributos; caso existam, e uma referência
com a tabela do pai, caso possua somente um pai. Possuindo mais de um pai, gera-se uma
tabela para o filho com seus respectivos atributos; caso existam, e uma tabela auxiliar
referenciando a tabela do filho e a tabela do pai.
Elemento filho (filho do elemento misto) é um PCDATA: ocorre da mesma
forma que a situação anterior.
Elemento vazio (filho do elemento misto): gera-se uma tabela para o filho,
com seus respectivos atributos; caso existam, e uma referência com a tabela do pai, caso
possua somente uma pai e o seu pai também possua semente um pai. Possuindo mais de
um pai, ambos os elementos, gera-se uma tabela para o filho com seus respectivos
atributos; caso existam, e uma tabela auxiliar referenciando a tabela do filho e a tabela do
53
pai.
Ainda nessa seção será abordado sobre esse mapeamento com mais detalhes. A
figura 28 mostra o início do mapeamento de elemento misto.
se for misto{gera uma tabela formada com o nome do pai e do filho, comuma coluna chave primaria e uma chave estrangeira quereferencia a tabela pai;se possui atributos{
addAtributosElemMisto(filho,pai);para cada filho do elemento misto{...}
}
Figura 28 – Inicio do algoritmo que trata de elemento misto.
Como pode ser visto na figura 28, após gerar a tabela para o elemento misto
percorre-se todos os filhos do elemento, fazendo o seu mapeamento para o modelo
relacional. Abaixo é descrito como são manipulados os filhos do elemento misto.
Primeiramente será tratado de elemento PCDATA.
se for PCDATA{se possui somente um pai{
gera uma tabela com uma coluna chave primaria, umacoluna chave estrangeira que referencia a tabela do paie uma coluna para o filho;
}senão{gera uma tabela para o filho com uma coluna chaveprimaria e uma coluna para o elemento filho;gera uma tabela auxiliar com duas coluna chavesestrangeira uma que referencia a tabela do filho e aoutra a tabela do pai;}
}
Figura 29 – Parte do algoritmo que trata de elemento misto – quando o filho do elemento misto é PCDATA.
Como mostra a figura 29, para elemento PCDATA faz-se duas verificações:
primeiro verifica-se se o elemento possui somente um pai; a segunda verificação é se o
elemento possui mais de um pai. Para a primeira condição, gera-se uma tabela para o
elemento referenciando a tabela do pai (elemento misto) e uma coluna para armazenar o
filho.
Na segunda condição gera-se uma tabela para o elemento PCDATA com uma coluna
chave primária e uma coluna para o elemento. Após, gera-se uma tabela auxiliar
54
referenciando a tabela do elemento misto a tabela do pai.
Caso o elemento não seja um PCDATA, percorre-se o documento e verifica-se onde
esse elemento é pai. Após encontrá-lo, são realizadas três condições: se o elemento
filho (filho do elemento misto) também possui filhos, se é um elemento
PCDATA e se é um elemento vazio.
A figura 30 mostra como é feito o mapeamento se o elemento filho também
possui filhos.
se o filho possui filho{se possui somente um pai{
gera uma tabela para o filho com uma coluna chaveprimário e uma coluna chave estrangeira quereferencia a tabela pai;se possui atributos{ addAtributosElemento(misto);}
}senão{gera uma tabela para filho com uma coluna chaveprimaria;se possui atributos{addAtributosElemento(misto);}gera uma tabela auxiliar com duas colunas chavesestrangeira uma que referencia a tabela do filho e aoutra a tabela do pai;}
}
Figura 30 – Parte do algoritmo que trata de elemento misto – quando o filhodo elemento misto possui filhos.
Como pode ser visto na figura 30, para esse tipo de elemento tem que ser analisados
duas condições: se o elemento filho do elemento misto possui somente um
pai; e se o elemento possui mais de um pai. Quando o elemento possui somente um pai,
gera-se uma tabela para o elemento filho com duas chaves, uma primária e outra
estrangeira que referencia a tabela do pai; caso possua atributos, eles são adicionados na
tabela.
Quando o elemento possui mais de um pai, gera-se uma tabela para o filho e
verifica-se se o mesmo possui atributos; se for verdade, adiciona-se os atributos à tabela.
Após, gera-se uma tabela auxiliar referenciando a tabela do filho e a tabela do pai.
A figura 31 mostra o mapeamento do elemento quando ele for um PCDATA.
55
se for um PCDATA{se possui somente um pai{
gera uma tabela para o filho com uma coluna chaveprimaria, uma coluna chave estrangeira que referenciaa tabela do pai e uma coluna para o elemento filho;se possui atributos{addAtributosElemento(misto);}
}senão{gera uma tabela para o filho com uma coluna chaveprimaria e uma coluna para o filho;se possui atributos{addAtributosElemento(misto);}gera uma tabela auxiliar com duas colunas chavesestrangeiras uma que referencia a tabela do filho e aoutra a tabela do pai;}
}
Figura 31 – Parte do algoritmo que trata de elemento misto – quando o filhodo elemento misto for um PCDATA.
A figura 31 descreve o mapeamento de quando o filho do elemento misto for do
tipo PCDATA. Como pode ser visto na figura 31, são realizadas duas verificações: se o
elemento possui somente um pai; e se o elemento possui mais de um pai. Para o elemento
que possui somente um pai, gera-se uma tabela referenciando a tabela do pai; caso possua
atributos, os mesmos são adicionados na tabela e também é adicionado na tabela uma
coluna para guardar o valor do elemento.
Quando o elemento possui mais de um pai, gera-se uma tabela para o filho com
uma coluna chave primária, uma coluna para o filho; caso possua atributos, os mesmos são
adicionados na tabela. Após, gera-se uma tabela auxiliar referenciando a tabela do filho e a
tabela do pai.
A figura 32 mostra o mapeamento de quando o filho do elemento misto
for um elemento vazio.
56
se for vazio{se possui somente um pai e seu pai possui somente um pai{
gera uma tabela para o filho com uma coluna chaveprimaria e uma coluna chave estrangeira que areferencia tabela pai;se possui atributos{ addAtributosElemento(misto);}
}senão{gera uma tabela para o filho com uma coluna chaveprimaria;se possui atributos{addAtributosElemento(misto);}gera uma tabela auxiliar com duas colunas chavesestrangeira uma que referencia a tabela do filho e aoutra a tabela do pai;}
}
Figura 32 – Parte do algoritmo que trata de elemento misto – quando o filhodo elemento misto for um elemento vazio.
Quando o filho do elemento misto for um elemento vazio verifica-
se duas condições: se o elemento filho possui somente um pai e se o seu pai (o
elemento misto) também possui somente um pai; e se o elemento filho possui mais de
um pai e se o seu pai (o elemento misto) também possui mais de um pai.
Para a primeira condição gera-se uma tabela para o filho com uma coluna chave
primária, uma coluna chave estrangeira que referencia a tabela do pai e seus atributos. Para
a segunda condição gera-se uma tabela para o filho com seus respectivos atributos e uma
tabela auxiliar referenciando a tabela do pai e a tabela do filho.
Na próxima seção têm-se uma abordagem do sistema implementado.
4.5 Sistema implementado
A implementação do algoritmo foi feita em Delphi 7. A ferramenta recebe um
documento XML (adquirido a partir do DTDParser do javacc), que é a representação da
DTD, e gera um script SQL (utilizado a sintaxe do SQL Server2000) . A figura 33 mostra a
interface do sistema implementado.
57
Figura 33 – Interface do sistema
Além de gerar os scripts SQL das DTDs, que é a sua função principal, o usuário
pode também realizar algumas operações básicas, como por exemplo, editar o documento
(mudar fonte, modificar o documento e dentre outras funcionalidades), imprimir etc. A
figura 34 mostra o modelo lógico relacional definido a partir do script SQL (da DTD da
figura 3) gerado pelo sistema implementado nesse trabalho.
58
Figura 34 – Modelo lógico relacional gerado a partir da DTD da figura 3.
Na próxima seção têm-se uma comparação entre os algoritmos apresentados na
seção 2.6 e o algoritmo desenvolvido nesse trabalho.
4.6 Comparação entre os algoritmos apresentados na revisão de literatura e o algoritmo desenvolvido nesse trabalho
Com base nos algoritmos apresentados na revisão de literatura e o algoritmo
desenvolvido nesse trabalho serão feitas algumas comparações:
1. Número de tabelas geradas: o número de tabelas geradas foi inferior a
praticamente todas as outras abordagens, com exceção da segunda
59
abordagem, que ficou com o mesmo número de tabelas. Entretanto, na
segunda abordagem, algumas tabelas geradas continham apenas a coluna
chave primária.
A vantagem de se obter um número menor de tabelas é que as consultas
tendem a apresentar uma melhor performance, uma vez que o número de
junções entre as tabelas é menor. Já com um número maior de tabelas,
obtém-se uma melhor normalização do modelo (menor redundância de
dados), mas isso aumenta a fragmentação e pode ocasionar perda de
performance;
2. Ordem dos elementos: somente a quarta abordagem (FLO 99) guarda a
ordem dos elementos.
A vantagem em guardar a ordem dos elementos é que , posteriormente,
pode-se recuperar o documento original do banco de dados;
3. A partir da DTD ou do XML: o algoritmo desenvolvido trabalha com base
em um DTD, assim como a primeira, a segunda e a terceira abordagens.
Somente a quarta abordagem baseia-se em um documento XML para a
geração de esquemas lógicos relacionais.
Ter como base uma DTD para gerar um modelo lógico relacional têm a
vantagem de que o modelo lógico gerado é válido para todos os documentos
XMLs válidos pela DTD. O caso de ter uma modelo relacional a partir de
um documento XML tem a desvantagem do modelo suportar somente uma
única estrutura (a estrutura do documento XML utilizada no mapeamento);
4. Informação não é perdida no mapeamento: tanto para o algoritmo
desenvolvido nesse trabalho quanto para os apresentados na revisão de
literatura não há perda no mapeamento.Todos os atributos e elementos são
mapeados para o modelo lógico relacional.
Guardar todas as informações contidas nos documentos pode gerar o
armazenamento de alguns dados desnecessários, como informações de
metadados armazenados em atributos, por exemplo. Por outro lado, todos os
dados do documento original são armazenados no banco;
5. Tabelas com apenas a chave primária: as abordagens apresentadas baseadas
em DTD geraram algumas tabelas com apenas a chave primária. Tabelas
60
apenas com chave primária devem ser analisadas e possivelmente integradas
a outras tabelas existentes no modelo. No algoritmo desenvolvido isso não
ocorre.
Essa situação ocorre em elementos em que todos os seus filhos são
multivalorados e no algoritmo desenvolvido ela está sendo tratada na parte
do algoritmo descrita na figura 26.
61
5. CONSIDERAÇÕES FINAIS E TRABALHOS FUTUROS
A proposta deste trabalho consistiu em definir uma algoritmo capaz de fazer o
mapeamento de uma DTD para um modelo lógico relacional, assim como a implementação
desse algoritmo.
Com o desenvolvimento do trabalho, foi possível gerar modelos lógicos relacionais
a partir de uma DTD, sem perder informações e mantendo a cardinalidade dos elementos e
atributos, possibilitando a extração de dados para o modelo lógico relacional de qualquer
documento XML válido pela DTD.
O DTDParser foi fundamental na leitura da DTD, permitindo gerar um documento
XML que representasse a DTD, fornecendo mais flexibilidade para trabalhar o
mapeamento. O XML Data Binding (Delphi) possibilitou fazer a leitura do documento
XML gerado pelo DTDParser, possibilitando assim a implementação do algoritmo.
Os principais problemas encontrados no desenvolvimento do trabalho foram:
mapeamento de elementos mistos; elementos complexos acrescidos do símbolo “*” e
“+”, como por exemplo, (<!ELEMENT secao
(paragrafo|figura|resumo|instituicao)+>); e elementos em que todos os
seus filhos são multivalorados. Essa última situação é uma das responsáveis pela criação de
tabelas com somente a chave primária, o que não acontece no algoritmo desenvolvido
nesse trabalho.
Como trabalhos futuros propõe-se adaptar ao algoritmo meios de mapear o caminho
(ordem) dos elementos e dos atributos do documento XML. Essa modificação facilitará a
recuperação do documento XML original. Um outro trabalho é o desenvolvimento de um
algoritmo que faça a recuperação do documento XML a partir do Banco de Dados
relacional.
O desenvolvimento desse trabalho possibilitou a definição de um algoritmo capaz
de fazer o mapeamento de uma DTD para um modelo lógico relacional e sua
implementação. Possibilitou também a exploração de componentes do Delphi (com por
63
6. REFERÊNCIAS BIBLIOGRÁFICAS
(AHO et al 1995) AHO, Alred V., SETHI Ravi, ULLMAN, Jeffrey D.,
Compiladores Principios, Técnicas e Ferramentas, Tradução Daniel de Ariosto
Pinto, Editora: Afiliada, Rio de Janeiro, RJ 1995
(ANDERSON 2001) ANDERSON, R. et al. Profissional XML. Rio de Janeiro,
RJ: Editora Ciência Moderna LTDA., 2001.
(BOU 2001) BOURRET, R. Mapping DTDs to Databases. Maio 2001.
Disponível em:<http://www.xml.com/pub/a/2001/05/09/dtdtodbs.html>. Acessado
em 08/10/2003
(CHR 94) CHRISTOPHIDES, V. et al. From structured documents to novel
query facilities. SIGMOD Record, New York, v.23, n.2, p. 313-324, June. 1994.
(DB2 2003a) DB2 Universal, IBM CORPORATIO. Disponível em
<http://www.ibm.com/db2> . Acessado em 27/09/2003
(DB2 2003b) XML Extender Administration and Programming, IBM
CORPORATIO. Disponível em <http://www.ibm.com.db2> . Acessado em
27/09/2003
(DB2 2003c) XML Extender, IBM CORPORATIO. Disponível em < http://www-
3.ibm.com/software/data/db2/extenders/xmlext/xmliseries/index.html > . Acessado
em 27/09/2003
64
(DTDParser 2003) DTDParser, Disponível em:
<http://www.cobase.cs.ucla.edu/pub/javacc/DTDParser.jj>. Acessado em
08/10/2003
(FER 98) FERNANDEZ, M. et al. Catching the Boat with Strudel: Experiences
with a Web-Site Management System. SIGMOD Record, New York, v.27, n.2, p.
414, 1998. Trabalho apresentado na ACM SIGMOD Special Interest Group on
Management of Data, SIGMOD, 1998.
(FLO 99) FLORESCU, D. et al. A Performance Evaluation of Alternative
Mapping Schemes for Storing XML Data in a Relational Database. 1999.
(Technical Report, n. 3680). Disponível em: <
http://citeseer.nj.nec.com/florescu99performance.html>. Acesso em: 25/09/2003.
(JAVACC 2000) JAVACC, Java Compiler Compiler, JavaCC versão 3.2
binaries, Disponível em:
<https://javacc.dev.java.net/servlets/ProjectDocumentList>. Acessado em
06/10/2003
(LU et al 2003) LU, Shiyong, SUN, Yezhou, Atay, Mustafa, FOTOUHI, Farshad.
A New Inlining Algorithm for Mapping XML DTDs to Relational Schemas,
Department Of Computer Science Wayne State University Detroit, MI 48202,
2003. Disponível em: <http://citeseer.nj.nec.com/lu03new.html> . Acessado em
29/09/2003.
(MELLO et al, 2000) MELLO, Ronaldo dos Santos, KADE, Adrovane Marques,
DORNELES, C. F., BRAGANHOLO, V.,HEUSER, Carlos Alberto, Dados Semi-
estruturados (tutorial). Simpósio Brasileiro de Banco de Dados, 2000, João
Pessoa, PB. Tutoriais. João Pessoa: SBC, 2000. Disponível em:
<ftp://heuser.inf.ufrgs.br/pub/pdf/sbbd00-tutorial.pdf>. Acesso em: 05/02/2003.
65
(McH2 97) McHUGH, J. et al. Lore: A Database Management System for
Semistructured Data. Disponível em: <http://www-
db.stanford.edu/lore/pubs/lore97.pdf>.SIGMOD Record, New York, v.26, n.3, p.
54-66, Sept. 1997. Acesso em: 26/09/2003.
(ORACLE 2002) ORACLE, Corporation, LORENTZ, Diana, GREGOIRE, Joan.
Oracle9i SQL Reference, Release 2 (9.2). outubro 2002. Disponívle em:
<ttp://www.arb.ca.gov/app/doc/oracle/doc92/SQLRef.pdf>. Acesso em: 26/09/2003
(SACCOL 2001) SACCOL, Deise de Brum, Materialização de Visões XML.
Dissertação (Mestrado) 2001. Programa de Pós-Graduação em Computação, Porto
Alegre, BR-RS, 2001. Universidade Federal do Rio Grande do Sul, Porto Alegre:
PPGC da UFRGS, 2001. 85 f:il. Orientador: Heuser, Carlos Alberto.
(SHA 99) SHANMUGASUNDARAM, J. et al. Relational Databases for
Querying XML Documents: Limitations and Opportunities. In:
INTERNATIONAL CONFERENCE ON VERY LARGE DATA BASES, 25.,
1999, Edinburg, UK. Proceedings... Edinburg: VLDB Endowment, 1999.
(SERVER 2000a) Microsoft SQL Server. Disponível em:
<http://www.microsoft.com/sql/evaluation/features/RichXML.asp> . Acessado em
27/09/2003.
(SERVER 2000b) Microsoft SQL Server. Disponível em: <
http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/dnsqlmag2k/html/TheXMLFiles.asp > . Acessado em 27/09/2003.
(ZWO 99) ZWOL, R. et al. Modelling and querying semistructured data with
MOA. In: WORKSHOP ON SEMI-STRUCTURED DATA AND
NONSTANDARD DATA FORMATS, 1999, Jerusalem, IS. Proceedings...
Jerusalem: VLDB Endowment, 1999.
67
DTDParse.jj
/*** name: DTDParser.jj* modified: Apr 2, 2001* author: John Gebbie* email: [email protected]*/
options {DEBUG_PARSER = false;
}
PARSER_BEGIN(DTDParser)
import java.io.InputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;
public class DTDParser{
public static void parse(InputStream aInSt) throws ParseException {// create a parser (this object)DTDParser parser = new DTDParser(aInSt);// parse!parser.dtd();
}
public static void main(String[] args) throws ParseException,FileNotFoundException {
parse(new FileInputStream(args[0]));}
}
PARSER_END(DTDParser)
TOKEN :{
<LETTER: [ "A"-"Z", "a"-"z" ] >| <DIGIT: [ "0"-"9" ] >| <NAMECHAR: ( <LETTER> | <DIGIT> | "." | "-" | "_" | ":" ) >| <FIXED: "#FIXED" >| <IMPLIED: "#IMPLIED" >| <PCDATA: "#PCDATA" >| <REQUIRED: "#REQUIRED" >| <CDATA: "CDATA" >| <ANY: "ANY" >| <EMPTY: "EMPTY" >| <ID: "ID" >| <IDREF: "IDREF" >| <IDREFS: "IDREFS" >| <ENTITY: "ENTITY" >| <ENTITIES: "ENTITIES" >| <NMTOKEN: "NMTOKEN" >| <NMTOKENS: "NMTOKENS" >| <NOTATION: "NOTATION" >| <NAME: ( <LETTER> | "_" | ":" ) ( <NAMECHAR> )* >
68
| <QUOTEDSTR: ( "'" (~["'"])* "'" ) | ( "\"" (~["\""])* "\"") >}
SKIP :{
< ( " " | "\t" | "\n" | "\r" )+ >// comment decl updated by Gagandeep Bhatia
[mailto:[email protected]]| < "<!--" ( ~["-"] | ( "-" ~["-"] ) )* "-->" >| < "<?" (~[">"])* ">" >}
void dtd() :{}{
{System.out.println("<DTD>");}( elementDecl() | attListDecl() )* <EOF>{System.out.println("</DTD>");}
}
void elementDecl() :{ Token t = new Token();}{
{System.out.println("<Elemento>");}
{System.out.println("<pai>");}
"<!ELEMENT" t = <NAME> contentSpec() ">"
{System.out.println("<nome>");}
{System.out.println(t.image);}
{System.out.println("</nome>");}
{System.out.println("</pai>");}
{System.out.println("</Elemento>");}}
void contentSpec() :{}{
{System.out.println("<tipo>");}{System.out.println("EMPTY");}<EMPTY>{System.out.println("</tipo>");}
|{System.out.println("<tipo>");}{System.out.println("ANY");}<ANY>{System.out.println("</tipo>");}
| LOOKAHEAD(3) mixed() | LOOKAHEAD(2) pcdata() | children()}
void pcdata() :{
69
}{
{System.out.println("<pcdata>");}
"(" <PCDATA> ")"
{System.out.println("PCDATA");}
{System.out.println("</pcdata>");}
}
void mixed() :{ Token t = new Token();}{
{System.out.println("<misto>");}
"(" {System.out.println("<nome>");} <PCDATA>{System.out.println("PCDATA");} {System.out.println("</nome>");} ("|" (t=<NAME> ){System.out.println("<nome>");}
{System.out.println(t.image);}
{System.out.println("</nome>");})+ ")*"
{System.out.println("</misto>");}
}
void children() :{}{
seqchoice() [modifier()]
}
void seqchoice() :{}{
"(" cp() ( choice() | seq() ) ")"}
void choice() :{}
70
{
( "|" cp() )+
}
void seq() :{}{
( "," cp() )*
}
void cp() :{ Token t = new Token();}{
{System.out.println("<filho>");}( t=<NAME> | seqchoice() ) [modifier()]
{System.out.println("<nome>");}
{System.out.println(t.image);}
{System.out.println("</nome>");}
{System.out.println("</filho>");}
}
void modifier() :{}{
{System.out.println("<modifier>");} {System.out.println("*");}"*" {System.out.println("</modifier>");}
| {System.out.println("<modifier>");} {System.out.println("+");}"+" {System.out.println("</modifier>");}
| {System.out.println("<modifier>");} {System.out.println("?");}"?" {System.out.println("</modifier>");}
}
void attListDecl() :{ Token t = new Token();}{
{System.out.println("<Atributos>");}"<!ATTLIST" t=<NAME> ( attribDef() )* ">"
{System.out.println("<ElementoRef>");}
{System.out.println(t.image);}
{System.out.println("</ElementoRef>");}
71
{System.out.println("</Atributos>");}
}
void attribDef() :{ Token t = new Token();}{
{System.out.println("<Atributo>");}
t=<NAME> attribType() defaultDecl()
{System.out.println("<nome>");}
{System.out.println(t.image);}
{System.out.println("</nome>");}
{System.out.println("</Atributo>");}
}
void attribType() :{}{
stringType() | tokenizedType() | enumeratedType()}
void stringType() :{}
{{System.out.println("<tipo>");}
{System.out.println("CDATA");} <CDATA>
{System.out.println("</tipo>");}
}
void tokenizedType() :{}{
{System.out.println("<tipo>");}
{System.out.println("ID");} <ID>{System.out.println("</tipo>");}|{System.out.println("<tipo>");}{System.out.println("IDREF");}<IDRE
F>{System.out.println("</tipo>");}|{System.out.println("<tipo>");}{System.out.println("IDREFS");}<IDR
EFS>{System.out.println("</tipo>");}|{System.out.println("<tipo>");}{System.out.println("ENTITY");}<ENT
ITY>{System.out.println("</tipo>");}|{System.out.println("<tipo>");}{System.out.println("ENTITIES");}<E
NTITIES>{System.out.println("</tipo>");}
72
|{System.out.println("<tipo>");}{System.out.println("NMTOKEN");}<NMTOKEN>{System.out.println("</tipo>");}
|{System.out.println("<tipo>");}{System.out.println("NMTOKENS");}<NMTOKENS>{System.out.println("</tipo>");}
}
void enumeratedType() :{}{
( notationType() | enumeration() )}
void notationType() :{Token t = new Token();}{
<NOTATION> "(" {System.out.println("<notation>");}t=<NAME> {System.out.println(t.image);}{System.out.println("</notation>");}
( "|" {System.out.println("<notation>");}t=<NAME> {System.out.println(t.image);}{System.out.println("</notation>");})* ")"
}
void enumeration() :{Token t = new Token();}{
"(" {System.out.println("<enumeration>");} t=<NAME>{System.out.println(t.image);}
{System.out.println("</enumeration>");}
( "|"{System.out.println("<enumeration>");}t=<NAME>{System.out.println(t.image);}
{System.out.println("</enumeration>");})* ")"
}
void defaultDecl() :{}{
{System.out.println("<DeclaracaoDefault>");}
<REQUIRED>{System.out.println("REQUIRED");}{System.out.println("</DeclaracaoDefault>");}
|{System.out.println("<DeclaracaoDefault>");}{System.out.println("IMPLIED");}<IMPLIED>{System.out.println("</DeclaracaoDefault>");}
|{System.out.println("<DeclaracaoDefault>");}{System.out.println("FIXED");}{System.out.println("</DeclaracaoDefault>");} ( [ <FIXED> ]attribValue() )
73
}
void attribValue() :{Token t = new Token();}{
{System.out.println("<attribValue>");}
t=<QUOTEDSTR>
{System.out.println(t.image);}
{System.out.println("</attribValue>");}
}
74
Implementação
unit Unit_principal;
interface
usesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,Dialogs, dtd, StdCtrls, Menus, Grids, ValEdit, Buttons, ExtCtrls,ComCtrls, ShellApi, WinTypes, WinProcs;
typeTForm_principal = class(TForm)
MainMenu1: TMainMenu;Arquivo: TMenuItem;Abrir: TMenuItem;Sair: TMenuItem;Salvar: TMenuItem;OpenDialog: TOpenDialog;Save: TSaveDialog;Mapeador: TMenuItem;DTDMR: TMenuItem;StatusBar1: TStatusBar;Panel: TPanel;SB_abrir: TSpeedButton;SP_salvar: TSpeedButton;SB_limpar: TSpeedButton;SB_mapeador: TSpeedButton;SB_sair: TSpeedButton;Label_tab: TLabel;Editar: TMenuItem;Limpar: TMenuItem;Ajuda: TMenuItem;Sobre: TMenuItem;Fonte: TMenuItem;FontDialog: TFontDialog;ValueListEditorTb: TValueListEditor;SB_font: TSpeedButton;PrintDialog: TPrintDialog;SpeedButton1: TSpeedButton;RichEdit: TRichEdit;Imprimir1: TMenuItem;procedure AbrirClick(Sender: TObject);procedure SalvarClick(Sender: TObject);procedure SairClick(Sender: TObject);procedure DTDMRClick(Sender: TObject);procedure SB_abrirClick(Sender: TObject);procedure SP_salvarClick(Sender: TObject);procedure SB_mapeadorClick(Sender: TObject);procedure SB_limparClick(Sender: TObject);procedure SB_sairClick(Sender: TObject);procedure LimparClick(Sender: TObject);
75
procedure FonteClick(Sender: TObject);procedure SB_fontClick(Sender: TObject);procedure SpeedButton1Click(Sender: TObject);procedure Imprimir1Click(Sender: TObject);
private{ Private declarations }
public{ Public declarations }cam: WideString;dtd: IXMLDTDType; elemento: IXMLElementoTypeList; atributos:
IXMLAtributosTypeList;procedure algoritmo();function getNumeroPai(str_filho: AnsiString): Integer;procedure addAtributosElementoPcdata(str_pai: AnsiString;
ElementoRef: AnsiString; modifier: AnsiString; cont_pai: Integer);procedure addAtributosElemento(ElementoRef: AnsiString);procedure addAtributosElemMisto(ElementoRef: AnsiString; str_pai:
AnsiString);function possuiAtributos(str_filho: AnsiString): Boolean;function possuiSoFilhosMultivalorados(str_elemento: AnsiString):
Boolean;function getKeyTb(str: AnsiString): Integer;procedure fileAbrir();procedure fileSave();
end;
varForm_principal: TForm_principal;
implementation
uses XMLIntf, Math;
{$R *.dfm}//----------procedure TForm_principal.fileAbrir();-----------------------------procedure TForm_principal.fileAbrir();
var str_file,str_file_aux: AnSistring;retornoShellex: Integer;
beginif OpenDialog.Execute thenbegin
str_file:=OpenDialog.FileName;try
str_file_aux:= 'DTDParser '+ str_file;if (DirectoryExists('C:\Program Files\Mapeador DTD\Mapeador
DTD\DTDParser')) then
retornoShellex:=ShellExecute(Application.Handle,'Open','java',PAnsiChar(str_file_aux),'C:\Program Files\Mapeador DTD\MapeadorDTD\DTDParser',SW_SHOWNORMAL)//SW_HIDE
else
retornoShellex:=ShellExecute(Application.Handle,'Open','java',Pchar(str_file_aux),'C:\Arquivos de programas\Mapeador DTD\MapeadorDTD\DTDParser',SW_SHOWNORMAL);//SW_HIDE
Delete(str_file,Pos('.',str_file),4);cam:= str_file+'.xml';
76
Sleep(retornoShellex*100);dtd:=LoadDTD(cam);elemento:=dtd.Elemento;atributos:=dtd.Atributos;RichEdit.Clear;ValueListEditorTb.Strings.Clear;RichEdit.Lines.Add(dtd.XML);SB_mapeador.Enabled:=True;DTDMR.Enabled:=True;Label_tab.Caption:='Representação do DTD em XML';except
ShowMessage('Arquivo incompatível!')end;
end;end;//----procedure TForm_principal.fileSave();------------------------------------procedure TForm_principal.fileSave();
var file_dados: TStringList;begin
file_dados:= TStringList.Create;if Save.Execute thenbegin
tryfile_dados.Add(RichEdit.Text);file_dados.SaveToFile(Save.FileName);ShowMessage('Arquivo salvo com sucesso!!');
finallyfile_dados.Free;
end;end;
end;//------function TForm_principal.getKeyTb(str: AnsiString): Integer;---------function TForm_principal.getKeyTb(str: AnsiString): Integer;
var z,pos_tb: Integer;begin
z:=1;pos_tb:=0;while z < ValueListEditorTb.RowCount dobegin
if ValueListEditorTb.Keys[z]=str thenbegin
pos_tb:=z;z:=ValueListEditorTb.RowCount;
end;//if ValueListEditorTb.Keys[z]='tb_'+str_pai thenz:=z+1;
end;//while z < ValueListEditorTb.RowCount dogetKeyTb:= pos_tb;
end;//------------------------------getNumeroPai--------------------------------function TForm_principal.getNumeroPai(str_filho: AnsiString): Integer;
var cont_pai,j,i: Integer;begin
cont_pai:=0;for j:=0 to elemento.Count - 1 dobegin
77
if elemento.Items[j].Pai.Filho.Count > 0 thenbegin
for i:=0 to elemento.Items[j].Pai.Filho.Count -1 dobegin
if Trim(elemento.Items[j].Pai.Filho.Items[i].Nome) =str_filho then
cont_pai:= cont_pai +1;end;//for i:=0 to elemento.Items[j].Pai.Filho.Count -1 do
end;//if elemento.Items[j].Pai.Filho.Count > 0 thenif elemento.Items[j].Pai.Misto.Count > 0 thenbegin
for i:=0 to elemento.Items[j].Pai.Misto.Count -1 dobegin
if Trim(elemento.Items[j].Pai.Misto.Nome[i]) = str_filhothen
cont_pai:= cont_pai +1;end;//for i:=0 to elemento.Items[j].Pai.Misto.Count -1 do
end;//if elemento.Items[j].Pai.Misto.Count > 0 thenend;//for j:=0 to elemento.Count - 1 dogetNumeroPai:=cont_pai;
end;//----------------------------functionTForm_principal.possuiSoFilhosMultivalorados(str_elemento: AnsiString):Boolean;----------function TForm_principal.possuiSoFilhosMultivalorados(str_elemento:AnsiString): Boolean;
var cont,j,i,aux: Integer;achou: Boolean; modifier: AnsiString;
begincont:=0;achou:=True;j:=0;while j < elemento.Count dobegin
aux:=j;if Trim(elemento.Items[aux].Pai.Nome) = str_elemento thenbegin
j:=elemento.Count;for i:=0 to elemento.Items[aux].Pai.Filho.Count -1 dobegin
modifier:=Trim(elemento.Items[aux].Pai.Filho.Items[i].Modifier);if (modifier = '') or (modifier='?') then
cont:= cont+1;end;//for i:=0 to elemento.Items[j].Pai.Filho.Count -1 do
end;//if elemento.Items[j].Pai.Filho.Count > 0 thenj:=j+1;
end;//while j < elemento.Count doif cont > 0 then
achou:=False;possuiSoFilhosMultivalorados:=achou;
end;//----------------------------function possuiAtributos(str_filho:AnsiString): Boolean;---function TForm_principal.possuiAtributos(str_filho: AnsiString): Boolean;
var i: Integer;achou: Boolean;
begini:=0;
78
achou:=False;while i < atributos.Count dobegin
if Trim(atributos.Items[i].ElementoRef) = str_filho thenbegin
achou:= True;i:=atributos.Count;
end;//if Trim(atributos.Items[i].ElementoRef) = str_filho theni:= i+1;
end;//while i < to atributos.Count dopossuiAtributos:= achou;
end;//--------addAtributosElementoPcdata(str_pai,str_filho:AnsiString,cont_pai: Integer);------------procedure TForm_principal.addAtributosElementoPcdata(str_pai: AnsiString;ElementoRef: AnsiString; modifier: AnsiString; cont_pai: Integer);
var i,j,pos_tb: Integer;key_tb,nome_atributo: AnsiString;
begini:=0;while i < atributos.Count dobegin
if Trim(atributos.Items[i].ElementoRef)= ElementoRef thenbegin
for j:=0 to atributos.Items[i].Atributo.Count - 1 dobegin
if Trim(atributos.Items[i].Atributo.Items[j].Tipo) <>'ID' then
begin
nome_atributo:=Trim(atributos.Items[i].Atributo.Items[j].Nome);if (cont_pai = 1) and ((modifier='') or
(modifier='?'))thenbegin
pos_tb:=getKeyTb('tb_'+str_pai);key_tb:='tb_'+str_pai;if pos_tb > 0 thenbegin
ifTrim(atributos.Items[i].Atributo.Items[j].Tipo)= 'IDREF' then
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' Integer not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if
Trim(atributos.Items[i].Atributo.Items[j].Tipo)= 'IDREF' thenelsebegin
ifTrim(atributos.Items[i].Atributo[j].DeclaracaoDefault) <>'IMPLIED' then
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' nvarchar(250) not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if
Trim(atributos.Items[i].Atributo[j].DeclaracaoDefault) <>'IMPLIED' thenelse
79
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' nvarchar(250)',True);
ValueListEditorTb.DeleteRow(pos_tb);end;//else
end;//elseend;//if pos_tb > 0 then
end//if cont_pai = 1 and ((modifier='') or(modifier='?'))then
elsebegin
if ((cont_pai = 1) and ((modifier='*') or(modifier='+'))) or (cont_pai > 1) then
beginpos_tb:=getKeyTb('tb_'+ElementoRef);key_tb:='tb_'+ElementoRef;if pos_tb > 0 thenbegin
ifTrim(atributos.Items[i].Atributo.Items[j].Tipo)= 'IDREF' then
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' Integer not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if
Trim(atributos.Items[i].Atributo.Items[j].Tipo)= 'IDREF' thenelsebegin
ifTrim(atributos.Items[i].Atributo[j].DeclaracaoDefault) <>'IMPLIED' then
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' nvarchar(250) not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if
Trim(atributos.Items[i].Atributo[j].DeclaracaoDefault) <>'IMPLIED' thenelsebegin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' nvarchar(250)',True);
ValueListEditorTb.DeleteRow(pos_tb);end;//else
end;//elseend;//if pos_tb > 0 then
end;// if ((cont_pai = 1) and ((modifier='*') or(modifier='+'))) or (cont_pai > 1) then
end;//elseend;//if Trim(atributos.Items[i].Atributo.Items[j].Tipo)
<> 'ID' thenend;//for j:=0 to atributos.Items[i].Atributo.Count - 1 do}i:=atributos.Count;
end;//if Trim(atributos.Items[i].ElementoRef)= ElementoRef theni:=i+1;
80
end;end;//-------------------------addAtributosElemento(ElementoRef: AnsiString)-------procedure TForm_principal.addAtributosElemento(ElementoRef: AnsiString);
var j,i,pos_tb: Integer;key_tb,nome_atributo: AnsiString;
begini:=0;while i < atributos.Count dobegin
if Trim(atributos.Items[i].ElementoRef)= ElementoRef thenbegin
for j:=0 to atributos.Items[i].Atributo.Count - 1 dobegin
if Trim(atributos.Items[i].Atributo.Items[j].Tipo) <>'ID' then
begin
nome_atributo:=Trim(atributos.Items[i].Atributo.Items[j].Nome);pos_tb:=getKeyTb('tb_'+ElementoRef);key_tb:='tb_'+ElementoRef;if pos_tb > 0 thenbegin
ifTrim(atributos.Items[i].Atributo.Items[j].Tipo)= 'IDREF' then
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' integer not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if
Trim(atributos.Items[i].Atributo.Items[j].Tipo)= 'IDREF' thenelsebegin
ifTrim(atributos.Items[i].Atributo[j].DeclaracaoDefault) <>'IMPLIED' then
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' nvarchar(250) not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if
Trim(atributos.Items[i].Atributo[j].DeclaracaoDefault) <>'IMPLIED' thenelsebegin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' nvarchar(250)',True);
ValueListEditorTb.DeleteRow(pos_tb);end;//else
end;//elseend;//if pos_tb > 0 then
end;//if Trim(atributos.Items[i].Atributo.Items[j].Tipo)<> 'ID' then
end;//for j:=0 to atributos.Items[i].Atributo.Count - 1 doi:=atributos.Count
end;//if Trim(atributos.Items[i].ElementoRef)= ElementoRef theni:= i+1;
81
end;//while i < atributos.Count doend;//--------TForm_principal.addAtributosElemMisto(ElementoRef: AnsiString;str_pai: AnsiString);-------procedure TForm_principal.addAtributosElemMisto(ElementoRef: AnsiString;str_pai: AnsiString);
var j,i,pos_tb: Integer;key_tb,nome_atributo: AnsiString;
begini:=0;while i < atributos.Count dobegin
if Trim(atributos.Items[i].ElementoRef)= ElementoRef thenbegin
for j:=0 to atributos.Items[i].Atributo.Count - 1 dobegin
if Trim(atributos.Items[i].Atributo.Items[j].Tipo) <>'ID' then
begin
nome_atributo:=Trim(atributos.Items[i].Atributo.Items[j].Nome);pos_tb:=getKeyTb('tb_'+ElementoRef+'_'+str_pai);key_tb:='tb_'+ElementoRef+'_'+str_pai;if pos_tb > 0 thenbegin
ifTrim(atributos.Items[i].Atributo.Items[j].Tipo)= 'IDREF' then
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' integer not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if
Trim(atributos.Items[i].Atributo.Items[j].Tipo)= 'IDREF' thenelsebegin
ifTrim(atributos.Items[i].Atributo[j].DeclaracaoDefault) <>'IMPLIED' then
begin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' nvarchar(250) not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if
Trim(atributos.Items[i].Atributo[j].DeclaracaoDefault) <>'IMPLIED' thenelsebegin
ValueListEditorTb.InsertRow(key_tb,Trim(ValueListEditorTb.Values[key_tb])+','+nome_atributo+' nvarchar(250)',True);
ValueListEditorTb.DeleteRow(pos_tb);end;//else
end;//elseend;//if pos_tb > 0 then
end;//if Trim(atributos.Items[i].Atributo.Items[j].Tipo)<> 'ID')
end;//for j:=0 to atributos.Items[i].Atributo.Count - 1 doi:=atributos.Count
end;//if Trim(atributos.Items[i].ElementoRef)= ElementoRef then
82
i:= i+1;end;//while i < atributos.Count do
end;//-------------------------algoritmo()-------------------------------------------procedure TForm_principal.algoritmo();
var j,i,y,pos_tb,aux_misto,aux,cont_pai,pos_tb_filho,cont_filho:Integer;
str_filho,modifier,str_pai,modifier_pai,modifier_aux,key_tb,pcdata,tipo,str_nome_misto,pcdata_misto,tipo_misto,key_tb_filho: AnsiString;achou: Boolean;
beginfor j:=0 to elemento.Count -1 dobegin
str_pai:= Trim(elemento.Items[j].Pai.Nome);modifier_pai:=Trim(elemento.Items[j].Pai.Modifier);for i:=0 to elemento.Items[j].Pai.Filho.Count -1 dobegin
str_filho:= Trim(elemento.Items[j].Pai.Filho.Items[i].Nome);modifier:=
Trim(elemento.Items[j].Pai.Filho.Items[i].Modifier);y:=1;while y <= elemento.Count-1 dobegin
if Trim(elemento.Items[y].Pai.Nome)=str_filho thenbegin
pcdata:=Trim(elemento.Items[y].Pai.Pcdata);tipo:= Trim(elemento.Items[y].Pai.Tipo);if elemento.Items[y].Pai.Filho.Count = 0 thenbegin
achou:=False;if getKeyTb('tb_'+str_pai) > 0 thenbegin
pos_tb:=getKeyTb('tb_'+str_pai);key_tb:='tb_'+str_pai;achou:=True;
end;//if getKeyTb('tb_'+str_pai) > 0 thenif not achou thenbegin
//cria uma tabela para o pai
ValueListEditorTb.InsertRow('tb_'+str_pai,'create table tb_'+str_pai+'(id_'+str_pai+' Integer not null, primary key (id_'+str_pai+')',True);
if possuiAtributos(str_pai) thenaddAtributosElemento(str_pai);
if getKeyTb('tb_'+str_pai) > 0 thenbegin
pos_tb:=getKeyTb('tb_'+str_pai);key_tb:='tb_'+str_pai;
end;//if getKeyTb('tb_'+str_pai) > 0 thenend;//if achou=False then
if pcdata ='PCDATA' thenbegin
cont_pai:=getNumeroPai(str_filho);if ((modifier_pai='+') or (modifier_pai='*'))
thenbegin
//cria uma tabela para o filho
83
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, primarykey (id_'+str_filho+'), id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai+', '+str_filho+' nvarchar(250)not null',True);
if possuiAtributos(str_filho) thenbegin
addAtributosElementoPcdata(str_pai,str_filho,modifier,cont_pai);end;//if possuiAtributos(str_filho)=True
thenend//if ((modifier_pai='+') or
(modifier_pai='*')) thenelsebegin
if (modifier='') or (modifier = '?') thenbegin
if not possuiAtributos(str_filho)then
begin//adiciona uma coluna na tabela
paiif modifier='' thenbegin
ValueListEditorTb.InsertRow('tb_'+str_pai,ValueListEditorTb.Values[key_tb]+', '+str_filho+' nvarchar(250) not null',True);
ValueListEditorTb.DeleteRow(pos_tb);end;//if modifier='' thenif modifier='?' thenbegin
ValueListEditorTb.InsertRow('tb_'+str_pai,ValueListEditorTb.Values[key_tb]+', '+str_filho+' nvarchar(250)',True);
ValueListEditorTb.DeleteRow(pos_tb);end;//if modifier='?' then
end//if possuiAtributos(str_filho)=false then
elsebegin
if cont_pai = 1 thenbegin
if modifier='?' thenbegin
ValueListEditorTb.InsertRow('tb_'+str_pai,ValueListEditorTb.Values[key_tb]+', '+str_filho+' nvarchar(250)',True);
ValueListEditorTb.DeleteRow(pos_tb);end//if modifier='?' thenelsebegin
ValueListEditorTb.InsertRow('tb_'+str_pai,ValueListEditorTb.Values[key_tb]+', '+str_filho+' nvarchar(250) not null',True);
84
ValueListEditorTb.DeleteRow(pos_tb);end;//else
end//if cont_pai = 1 thenelsebegin
achou:=False;if getKeyTb('tb_'+str_filho)
> 0 thenbegin
achou:=True;end;//if
getKeyTb('tb_'+str_filho) > 0 thenif not achou thenbegin
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+'), '+str_filho+' nvarchar(250) not null',True);
if modifier ='?' thenbegin //adiciona o id
do tb filho na tabela pai
ValueListEditorTb.InsertRow('tb_'+str_pai,ValueListEditorTb.Values[key_tb]+', id_'+str_filho+' Integer, foreign key (id_'+str_filho+') referencestb_'+str_filho,True)
end//if modifier ='?'then
elsebegin
ValueListEditorTb.InsertRow('tb_'+str_pai,ValueListEditorTb.Values[key_tb]+', id_'+str_filho+' Integer not null, foreign key (id_'+str_filho+')references tb_'+str_filho,True);
end;//else
ValueListEditorTb.DeleteRow(pos_tb);end;//else
addAtributosElementoPcdata(str_pai,str_filho,modifier,cont_pai);end;//if achou=False then
end;//elseend//if modifier='' or modifier = '?'
thenelsebegin
if (modifier='*') or (modifier = '+')then
beginif not possuiAtributos(str_filho)
thenbegin
//gera uma nova tabela com oid do pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, primarykey (id_'+str_filho+'), id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai+', '+
85
str_filho+' nvarchar(250) notnull',True);
end//if notpossuiAtributos(str_filho) then
elsebegin
if cont_pai =1 thenbegin
//gera uma nova tabelacom o id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+'), id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai+', '+
str_filho+' nvarchar(250)not null',True);
addAtributosElementoPcdata(str_pai,str_filho,modifier,cont_pai);end//if cont_pai:=1 thenelsebegin
achou:=False;if
getKeyTb('tb_'+str_filho) > 0 thenbegin
achou:=True;end;//if
getKeyTb('tb_'+str_filho) > 0 thenif not achou thenbegin
//cria uma tabelapara o filho
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+')',True);
addAtributosElementoPcdata(str_pai,str_filho,modifier,cont_pai);end;//if achou=False then//cria uma tabela
auxiliar com o id do pai e o id do filho
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, foreignkey (id_'+str_filho+') references tb_'+str_filho+', id_'+str_pai+'Integer not null, foreign key (id_'+str_pai+') references tb_'+str_pai+',primary key (id_'+str_filho+',id_'+str_pai+')',True);
end;//elseend;//else
end;//if modifier='*' or modifier ='+' then
end;//elseend;//else
end;//if pcdata <>'' thenend//if elemento.Items[y].Pai.Filho.Count = 0 thenelsebegin
if elemento.Items[y].Pai.Filho.Count > 0 then
86
beginmodifier_aux:=
Trim(elemento.Items[y].Pai.Modifier);cont_pai:= getNumeroPai(str_filho);if (((modifier ='*') or (modifier='+')) and
((modifier_aux='*') or (modifier_aux='+'))) thenbegin
if cont_pai = 1 thenbegin
//cria uma tabela para o filho com oid do pai
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+'), id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai,True);
if possuiAtributos(str_filho) thenaddAtributosElemento(str_filho);
end//if cont_pai = 1 thenelsebegin
//cria uma tabela p/ guardar o id dopai e o id do filho
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, foreignkey (id_'+str_filho+') references tb_'+str_filho+', id_'+str_pai+'Integer not null, foreign key (id_'+str_pai+') references tb_'+str_pai+',primary key(id_'+str_filho+',id_'+str_pai+')',True);
achou:=False;if getKeyTb('tb_'+str_filho) > 0 thenbegin
achou:=True;end;//if getKeyTb('tb_'+str_filho) >
0 thenif not achou thenbegin
//cria uma tabela p/ o filho
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+')',True);
if possuiAtributos(str_filho)then
addAtributosElemento(str_filho);end;//if achou=False then
end;//elseend;//if (modifier ='*' or modifier='+') and
(modifier_aux='*' or modifier_aux='+') thenif (((modifier ='') or (modifier='?')) and
((modifier_aux='*') or (modifier_aux='+'))) thenbegin
if cont_pai = 1 thenbegin
//cria uma tabela para o filho com oid do pai
ValueListEditorTb.InsertRow('tb_'+str_filho,'create table
87
tb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+'), id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai,True);
if possuiAtributos(str_filho)thenaddAtributosElemento(str_filho);
end//if cont_pai = 1 thenelsebegin
//cria uma tabela p/ guardar o id dopai e o id do filho
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, foreignkey (id_'+str_filho+') references tb_'+str_filho+', id_'+str_pai+'Integer not null, foreign key (id_'+str_pai+') references tb_'+str_pai+',primary key (id_'+str_filho+',id_'+str_pai+')',True);
achou:=False;if getKeyTb('tb_'+str_filho) > 0 thenbegin
achou:=True;end;//if getKeyTb('tb_'+str_filho) >
0 thenif not achou thenbegin
//cria uma tabela par o filho
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+')',True);
if possuiAtributos(str_filho)then
addAtributosElemento(str_filho);end;//if achou=False then
end;//elseend;//if (modifier ='' or modifier='?') and
(modifier_aux='*' or modifier_aux='+') thenif (((modifier ='*') or (modifier='+')) and
((modifier_aux=''))) thenbegin
if cont_pai = 1 thenbegin
//cria uma tabela para o filho com oid do pai
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+'), id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai,True);
if possuiAtributos(str_filho) thenaddAtributosElemento(str_filho);
end//if cont_pai = 1 thenelsebegin
//cria uma tabela para o filhoachou:=False;if getKeyTb('tb_'+str_filho) > 0 thenbegin
achou:=True;
88
end;//if getKeyTb('tb_'+str_filho) >0 then
if not achou thenbegin
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+')',True);
if possuiAtributos(str_filho)then
addAtributosElemento(str_filho);end;//if achou then//cria uma tabela auxilara com o id
do filho e o id da tabela pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, foreignkey (id_'+str_filho+') references tb_'+str_filho+', id_'+str_pai+'Integer not null, foreign key (id_'+str_pai+') references tb_'+str_pai+',primary key (id_'+str_filho+',id_'+str_pai+')',True);
end;//elseend;//if ((modifier ='*') or (modifier='+'))
and ((modifier_aux='')) then
if ((modifier ='') or (modifier='?') and(modifier_aux='')) then
beginif (modifier_pai = '*') or (modifier_pai
= '+') thenbegin
if cont_pai = 1 thenbegin
//cria uma taebla para o filhocom o id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+'),' +'id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai,True);
if possuiAtributos(str_filho)then
addAtributosElemento(str_filho);end//if cont_pai = 1 thenelsebegin
//cria uma tabela para o filhoachou:=False;if getKeyTb('tb_'+str_filho) > 0
thenbegin
achou:=True;end;//if
getKeyTb('tb_'+str_filho) > 0 thenif not achou thenbegin
ValueListEditorTb.InsertRow('tb_'+str_filho,'create table
89
tb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+')',True);
if possuiAtributos(str_filho)then
addAtributosElemento(str_filho);end;//if achou then//cria uma tabela auxiliar com o
id filho e o id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, foreignkey (id_'+str_filho+') references tb_'+str_filho+', id_'+str_pai+'Integer not null, foreign key (id_'+str_pai+') references tb_'+str_pai+',primary key (id_'+str_filho+',id_'+str_pai+')',True);
end;//elseend//if (modifier_pai = '*') or
(modifier_pai = '+') thenelsebegin
if notpossuiSoFilhosMultivalorados(str_filho) then
begin//adiciona o id do filho na
tabela paiachou:=False;if getKeyTb('tb_'+str_pai) > 0
thenbegin
pos_tb:=getKeyTb('tb_'+str_pai);key_tb:='tb_'+str_pai;achou:=True;
end;//if getKeyTb('tb_'+str_pai)> 0 then
if not achou thenbegin
//cria uma tabela para o pai
ValueListEditorTb.InsertRow('tb_'+str_pai,'create table tb_'+str_pai+'(id_'+str_pai+' Integer not null, primary key (id_'+str_pai+')',True);
if possuiAtributos(str_pai)then
addAtributosElemento(str_pai);
if getKeyTb('tb_'+str_pai) >0 then
begin
pos_tb:=getKeyTb('tb_'+str_pai);key_tb:='tb_'+str_pai;
end;//ifgetKeyTb('tb_'+str_pai) > 0 then
end;//if achou=False then//adiciona o id do filho na
tabela paiif modifier <>'?' thenbegin
90
ValueListEditorTb.InsertRow(ValueListEditorTb.Keys[pos_tb],
ValueListEditorTb.Values[key_tb]+', '+'id_'+str_filho+' Integer not null,foreign key (id_'+str_filho+') references tb_'+str_filho,True);
ValueListEditorTb.DeleteRow(pos_tb);end//if modifier ='' thenelsebegin
ValueListEditorTb.InsertRow(ValueListEditorTb.Keys[pos_tb],
ValueListEditorTb.Values[key_tb]+', '+'id_'+str_filho+' Integer, foreignkey (id_'+str_filho+') references tb_'+str_filho,True);
ValueListEditorTb.DeleteRow(pos_tb);end;//else
end//if notpossuiSoFilhosMultivalorados(str_filho) then
elsebegin
//cria uma tabela para o filhocom o id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+'), id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai,True);
if possuiAtributos(str_filho)then
addAtributosElemento(str_filho);end;//esle
end;//elseend;//if ((modifier ='') or (modifier='?'))
and ((modifier_aux='')) thenend;//if elemento.Items[y].Pai.Filho.Count > 0
thenend;//else//elemeneto vazioif tipo = 'EMPTY' thenbegin
if (modifier ='') or (modifier='?') thenbegin
if (modifier_pai = '*') or (modifier_pai ='+') then
begin//cria uma tabela com o id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, primarykey (id_'+str_filho+'),' +'id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai,True);
if possuiAtributos(str_filho) then
addAtributosElemMisto(str_filho,str_pai);end//if (modifier_pai = '*') or (modifier_pai
= '+') then
91
elsebegin
//cria uma tabela para o elemento vazioachou:=False;if getKeyTb('tb_'+str_filho) > 0 thenbegin
achou:=True;end;//if getKeyTb('tb_'+str_filho) > 0
thenif not achou thenbegin
//cria uma tabela para o filho
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+')',True);
if possuiAtributos(str_filho) thenbegin
addAtributosElemento(str_filho);end;//if possuiAtributos(str_filho) =
True thenend;//if achou=False then//adiciona o id do filho na tabela paiachou:=False;if getKeyTb('tb_'+str_pai) > 0 thenbegin
pos_tb:=getKeyTb('tb_'+str_pai);key_tb:='tb_'+str_pai;achou:=True;
end;//if getKeyTb('tb_'+str_pai) > 0 thenif not achou thenbegin
//cria uma tabela p/ pai
ValueListEditorTb.InsertRow('tb_'+str_pai,'create table tb_'+str_pai+'(id_'+str_pai+' Integer not null, primary key (id_'+str_pai+')',True);
if possuiAtributos(str_filho) thenbegin
addAtributosElemento(str_filho);end;//if possuiAtributos(str_filho) =
True thenif getKeyTb('tb_'+str_pai) > 0 thenbegin
pos_tb:=getKeyTb('tb_'+str_pai);key_tb:='tb_'+str_pai;
end;//if getKeyTb('tb_'+str_pai) > 0then
end;//if achou=False then//adiciona o id do filho na tabela do paiif modifier<>'?'thenbegin
ValueListEditorTb.InsertRow(ValueListEditorTb.Keys[pos_tb],ValueListEditorTb.Values[key_tb]+',
'+'id_'+str_filho+' Integer not null, foreign key (id_'+str_filho+')references tb_'+str_filho,True);
ValueListEditorTb.DeleteRow(pos_tb);end//if modifier=''thenelse
92
begin
ValueListEditorTb.InsertRow(ValueListEditorTb.Keys[pos_tb],ValueListEditorTb.Values[key_tb]+',
'+'id_'+str_filho+' Integer, foreign key (id_'+str_filho+') referencestb_'+str_filho,True);
ValueListEditorTb.DeleteRow(pos_tb);end;//else
end;//elseend//if (modifier ='') or (modifier='?') thenelsebegin
if (modifier ='*') or (modifier='+') thenbegin
//cria uma tabela para o elemento vazioachou:=False;if getKeyTb('tb_'+str_filho) > 0 thenbegin
achou:=True;end;//if getKeyTb('tb_'+str_filho) > 0
thenif not achou thenbegin
//cria uma tabela para o filho
ValueListEditorTb.InsertRow('tb_'+str_filho,'create tabletb_'+str_filho+' (id_'+str_filho+' Integer not null, primary key(id_'+str_filho+')',True);
//inserir atributosif possuiAtributos(str_filho) thenbegin
addAtributosElemento(str_filho);end;//if possuiAtributos(str_filho) =
True thenend;//if achou=False then//cria uma tabela auxiliar com o id do
filho e do pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, foreignkey (id_'+str_filho+') references tb_'+str_filho+', id_'+str_pai+'Integer not null, foreign key (id_'+str_pai+') references tb_'+str_pai+',primary key (id_'+str_filho+',id_'+str_pai+')',True);
end;//if (modifier ='*') or (modifier='+')then
end;//else
end;//if tipo <> '' then//elemento mistoif elemento.Items[y].Pai.Misto.Count > 0 thenbegin
//cria uma tabela para o filho com o id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai,'create tabletb_'+str_filho+'_'+str_pai+' (id_'+str_filho+' Integer not null, primarykey (id_'+str_filho+'), id_'+str_pai+' Integer not null, foreign key(id_'+str_pai+') references tb_'+str_pai,True);
if possuiAtributos(str_filho) thenaddAtributosElemMisto(str_filho,str_pai);
93
for aux_misto:=0 to elemento.Items[y].Pai.Misto.Count-1 do
begin
str_nome_misto:=Trim(elemento.Items[y].Pai.Misto.Nome[aux_misto]);cont_pai:=getNumeroPai(str_nome_misto);if str_nome_misto='PCDATA' thenbegin
if cont_pai = 1 thenbegin
//cria um tabela para o elemento mistocom o id de seu pai
ValueListEditorTb.InsertRow('tb_PCDATA','create table tb_pcdata(id_pcdata Integer not null, primary key (id_pcdata), id_'+str_filho+'Integer not null, foreign key (id_'+str_filho+') referencestb_'+str_filho+'_'+str_pai+', PCDATA nvarchar(250) not null',True);
end//if cont_pai = 1 thenelsebegin
achou:=False;if getKeyTb('tb_PCDATA') > 0 thenbegin
achou:=True;end;//if getKeyTb('tb_PCDATA') > 0 thenif not achou thenbegin
//cria uma tabela para o elementomisto
ValueListEditorTb.InsertRow('tb_PCDATA','create table tb_pcdata(id_pcdata Integer not null, primary key (id_pcdata), PCDATAnvarchar(250) not null',True);
end;//if achou=False then//cria uma tabela com o id elemento
misto, do pai e do avô
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai+'_PCDATA','createtable tb_'+str_filho+'_'+str_pai+'_PCDATA (id_pcdata Integer not null,foreign key (id_pcdata) references tb_pcdata, id_'+str_filho+' Integernot null, foreign key (id_'+str_filho+') referencestb_'+str_filho+'_'+str_pai,True);
end;//elseend//if str_nome_misto='PCDATA' thenelsebegin
for aux:=1 to elemento.Count - 1 dobegin
if Trim(elemento.Items[aux].Pai.Nome) =str_nome_misto then
begin
pcdata_misto:=Trim(elemento.Items[aux].Pai.Pcdata);
tipo_misto:=Trim(elemento.Items[aux].Pai.Tipo);if
elemento.Items[aux].Pai.Filho.Count > 0 thenbegin
if cont_pai = 1 then
94
begin//cria uma tabela para o
elemento misto com o id de seu pai
ValueListEditorTb.InsertRow('tb_'+str_nome_misto,'create tabletb_'+str_nome_misto+'(id_'+str_nome_misto+' Integer not null, primary key(id_'+str_nome_misto+'), id_'+str_filho+' Integer not null, foreign key(id_'+str_filho+') references tb_'+str_filho+'_'+str_pai,True);
ifpossuiAtributos(str_nome_misto) then
addAtributosElemento(str_nome_misto);end// if cont_pai = 1 thenelsebegin
if cont_pai > 1 thenbegin
achou:=False;if
getKeyTb('tb_'+str_nome_misto) > 0 thenbegin
achou:=True;end;//if
getKeyTb('tb_'+str_nome_misto) > 0 thenif achou=False thenbegin
//cria uma tabelapara o elemento misto
ValueListEditorTb.InsertRow('tb_'+str_nome_misto,'create tabletb_'+str_nome_misto+' (id_'+str_nome_misto+' Integer not null, primarykey (id_'+str_nome_misto+')',True);
ifpossuiAtributos(str_nome_misto) then
addAtributosElemento(str_nome_misto);end;//if achou=False then//cria uma tabela
auxiliar com o id do elemento misto, id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai+'_'+str_nome_misto,'create table tb_'+str_filho+'_'+str_pai+'_'+str_nome_misto+'(id_'+str_nome_misto+' Integer not null, foreign key(id_'+str_nome_misto+') references tb_'+str_nome_misto+',id_'+str_filho+' Integer not null, foreign key (id_'+str_filho+')references tb_'+str_filho+'_'+str_pai+', primary key(id_'+str_nome_misto+')',True);
end;//if cont_pai > 1 thenend;//else
end//ifelemento.Items[aux].Pai.Filho.Count > 0 then
elsebegin
ifelemento.Items[aux].Pai.Filho.Count = 0 then
begin//cria um tabela para o
elemento e adiciona o id do pai
95
if pcdata_misto = 'PCDATA'then
beginif cont_pai = 1 thenbegin
//cria uma tabelapara o elemento misto, id do pai e o id de seu avô
ValueListEditorTb.InsertRow('tb_'+str_nome_misto,'create tabletb_'+str_nome_misto+' (id_'+str_nome_misto+' Integer not null, primarykey (id_'+str_nome_misto+'), '+'id_'+str_filho+' Integer not null,foreign key (id_'+str_filho+') references tb_'+str_filho+'_'+str_pai+','+str_nome_misto+' nvarchar(250) not null',True);
ifpossuiAtributos(str_nome_misto) then
addAtributosElemento(str_nome_misto);end//if cont_pai = 1
thenelsebegin
if cont_pai > 1then
beginachou:=False;if
getKeyTb('tb_'+str_nome_misto) > 0 thenbegin
achou:=True;end;//if
getKeyTb('tb_'+str_nome_misto) > 0 thenif achou=False
thenbegin
//cria umatabela para o elemento misto
ValueListEditorTb.InsertRow('tb_'+str_nome_misto,'create tabletb_'+str_nome_misto+' (id_'+str_nome_misto+' Integer not null, primarykey (id_'+str_nome_misto+'),'+str_nome_misto+' nvarchar(250) notnull',True);
ifpossuiAtributos(str_nome_misto) then
addAtributosElemento(str_nome_misto);end;//if
achou=False then//cria uma
tabela auxiliar com o id do elemento misto, id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai+'_'+str_nome_misto,'create table tb_'+str_filho+'_'+str_pai+'_'+str_nome_misto+'(id_'+str_nome_misto+' Integer not null, foreign key(id_'+str_nome_misto+') references tb_'+str_nome_misto+',id_'+str_filho+' Integer not null, foreign key (id_'+str_filho+')references tb_'+str_filho+'_'+str_pai+', primary key(id_'+str_nome_misto+')',True);
96
end;//if cont_pai >1 then
end;//elseend//if pcdata_misto =
'PCDATA' thenelsebegin
if tipo_misto = 'EMPTY'then
beginif (cont_pai = 1)
and (getNumeroPai(str_filho)=1) thenbegin
//cria umatabela para o elemento misto, id do pai
ValueListEditorTb.InsertRow('tb_'+str_nome_misto,'create tabletb_'+str_nome_misto+' (id_'+str_nome_misto+' Integer not null, primarykey (id_'+str_nome_misto+'), '+'id_'+str_filho+' Integer not null,foreign key (id_'+str_filho+') references tb_'+str_filho+'_'+str_pai+','+str_nome_misto+' nvarchar(250) not null',True);
//atribui osatributos na tabela
ifpossuiAtributos(str_nome_misto) = True then
addAtributosElemento(str_nome_misto);
//addAtributosElemento(str_nome_misto);end//if cont_pai =
1 thenelsebegin
if (cont_pai >1) or (getNumeroPai(str_filho)>1) then
begin
achou:=False;if
getKeyTb('tb_'+str_nome_misto) > 0 thenbegin
achou:=True;end;//if
getKeyTb('tb_'+str_nome_misto) > 0 thenif
achou=False thenbegin
//criauma tabela para o elemento misto
ValueListEditorTb.InsertRow('tb_'+str_nome_misto,'create tabletb_'+str_nome_misto+' (id_'+str_nome_misto+' Integer not null, primarykey (id_'+str_nome_misto+'),'+str_nome_misto,True);
ifpossuiAtributos(str_nome_misto) = True then
addAtributosElemento(str_nome_misto);
97
end;//ifachou=False then
//cria umatabela auxiliar com o id do elemento misto, id do pai
ValueListEditorTb.InsertRow('tb_'+str_filho+'_'+str_pai+'_'+str_nome_misto,'create table tb_'+str_filho+'_'+str_pai+'_'+str_nome_misto+'(id_'+str_nome_misto+' Integer not null, foreign key(id_'+str_nome_misto+') references tb_'+str_nome_misto+',id_'+str_filho+' Integer not null, foreign key (id_'+str_filho+')references tb_'+str_filho+'_'+str_pai+', primary key(id_'+str_nome_misto+')',True);
end;//ifcont_pai > 1 then
end;//elseend;//if tipo_misto =
'EMPTY' thenend;//else
end;//ifelemento.Items[aux].Pai.Filho.Count = 0 then
end;//elseend;//if
Trim(elemento.Items[aux].Pai.Nome) = str_nome_misto thenend;//for aux:=1 to elemento.Count - 1 do
end;//else
end;//for aux_misto:=0 toelemento.Items[y].Pai.Misto.Count -1 do
end;//if elemento.Items[y].Pai.Misto.Count > 0 theny:= elemento.Count;
end;//if Trim(elemento.Items[y].Pai.Nome)=str_filho theny:= y+1;
end;//while y < elemento.Count doend;//for i:=0 to elemento.Items[j].Pai.Filho.Count -1 do
end;//for j:=0 to elemento.Count -1 doend;
procedure TForm_principal.AbrirClick(Sender: TObject);begin
fileAbrir();end;
procedure TForm_principal.SalvarClick(Sender: TObject);begin
fileSave();end;
procedure TForm_principal.SairClick(Sender: TObject);begin
Close;end;
procedure TForm_principal.DTDMRClick(Sender: TObject);var i:Integer;
beginValueListEditorTb.Strings.Clear;algoritmo();RichEdit.Clear;
98
RichEdit.Lines.Add('create database'+Trim(elemento.Items[0].Pai.Nome));
for i:=1 to ValueListEditorTb.RowCount - 1 dobegin
RichEdit.Lines.Add('');
RichEdit.Lines.Add(Trim(ValueListEditorTb.Values[ValueListEditorTb.Keys[i]])+');');
end;DTDMR.Enabled:=False;SB_mapeador.Enabled:=False;Label_tab.Caption:='Modelo Relacional Gerado a partir do DTD.';
end;
procedure TForm_principal.SB_abrirClick(Sender: TObject);begin
fileAbrir();end;
procedure TForm_principal.SP_salvarClick(Sender: TObject);begin
fileSave();end;
procedure TForm_principal.SB_mapeadorClick(Sender: TObject);var i:Integer;
beginValueListEditorTb.Strings.Clear;algoritmo();RichEdit.Clear;RichEdit.Lines.Add('create database
'+Trim(elemento.Items[0].Pai.Nome));for i:=1 to ValueListEditorTb.RowCount - 1 dobegin
RichEdit.Lines.Add('');
RichEdit.Lines.Add(Trim(ValueListEditorTb.Values[ValueListEditorTb.Keys[i]])+');');
end;Label_tab.Caption:='Modelo Relacional Gerado a partir do DTD.';
end;
procedure TForm_principal.SB_limparClick(Sender: TObject);begin
Label_tab.Caption:='Mapeador de DTD/Modelo Relacional';RichEdit.Clear;ValueListEditorTb.Strings.Clear;
end;
procedure TForm_principal.SB_sairClick(Sender: TObject);begin
Close;end;
procedure TForm_principal.LimparClick(Sender: TObject);begin
Label_tab.Caption:='Mapeador de DTD/Modelo Relacional';RichEdit.Clear;ValueListEditorTb.Strings.Clear;
99
end;
procedure TForm_principal.FonteClick(Sender: TObject);begin
if FontDialog.Execute thenbegin
tryRichEdit.Font.Color:=FontDialog.Font.Color;RichEdit.Font.Size:=FontDialog.Font.Size;RichEdit.Font.Style:=FontDialog.Font.Style;
ExceptShowMessage('Não foi possui alterar a fonte');
end;end;
end;
procedure TForm_principal.SB_fontClick(Sender: TObject);begin
if FontDialog.Execute thenbegin
tryRichEdit.Font.Color:=FontDialog.Font.Color;RichEdit.Font.Size:=FontDialog.Font.Size;RichEdit.Font:=FontDialog.Font;
ExceptShowMessage('Não foi possui alterar a fonte');
end;end;
end;
procedure TForm_principal.SpeedButton1Click(Sender: TObject);var contPrint: Integer;
begintry
if PrintDialog.Execute thenbegin
for contPrint:=1 to PrintDialog.Copies doRichEdit.Print(RichEdit.Lines.Text);
end;Except
ShowMessage('Não existe impressora instalada!');end;
end;
procedure TForm_principal.Imprimir1Click(Sender: TObject);var contPrint: Integer;
begintry
if PrintDialog.Execute thenbegin
for contPrint:=1 to PrintDialog.Copies doRichEdit.Print(RichEdit.Lines.Text);
end;Except
ShowMessage('Não existe impressora instalada!');end;
end;