You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdewebdev/quanta/parsers/dtd/dtd.cpp

416 lines
11 KiB

/***************************************************************************
dtdparser.cpp - description
-------------------
begin : Tue Jul 30 15:26:20 EEST 2002
copyright : (C) 2002 by Jason P. Hanley <jphanley@buffalo.edu>
(C) 2002, 2003 Andras Mantia <amantia@kde.org>
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <tqfile.h>
#include <tqfileinfo.h>
#include <tqregexp.h>
#include <tqstringlist.h>
#include <tqdom.h>
#include <klocale.h>
#include <kurl.h>
#include <kdebug.h>
#include <kio/netaccess.h>
#include <kmessagebox.h>
#include <ktempfile.h>
#include "dtd.h"
#include "../tquantacommon.h"
#include "../tqextfileinfo.h"
DTD::DTD(const KURL &dtdURL, const TQString &dtepDir)
{
m_dtdURL = dtdURL;
m_dtepDir = dtepDir + "/"+TQFileInfo(dtdURL.fileName()).baseName(); //TODO: get the dir name from the DTD or from the user
}
DTD::~DTD()
{
}
TQStringList DTD::getTags()
{
return tags;
}
AttributeList* DTD::getTagAttributes(TQString tag)
{
return tagAttributes.tqfind(tag);
}
TQStringList DTD::getTextCompletion(TQString tag)
{
return TQStringList();
}
void DTD::printContents()
{
for ( TQStringList::Iterator tagIt = tags.begin(); tagIt != tags.end(); ++tagIt ) {
TQString tag = *tagIt;
kdDebug(24000) << tag << endl;
AttributeList *attributes = getTagAttributes(tag);
for ( uint i = 0; i < attributes->count(); i++)
{
Attribute *attribute = attributes->at(i);
TQString s = " " + attribute->name + ": ";
for (uint j = 0; j < attribute->values.count(); j++)
{
s += attribute->values[j] + ", ";
}
kdDebug(24000) << s << endl;
}
}
}
void DTD::writeTagFiles()
{
TQString dirName = m_dtepDir;
KURL u;
u.setPath(dirName);
if (!TQExtFileInfo::createDir(dirName)) {
QuantaCommon::dirCreationError(0, u);
return;
}
dirName.append("/");
for ( TQStringList::Iterator tagIt = tags.begin(); tagIt != tags.end(); ++tagIt ) {
TQString tag = *tagIt;
TQFile file( dirName + tag.lower() + ".tag" );
if ( file.open( IO_WriteOnly ) ) {
TQTextStream stream( &file );
stream.setEncoding(TQTextStream::UnicodeUTF8);
stream << "<!DOCTYPE TAGS>" << endl
<< "<TAGS>" << endl
<< "<tag name=\"" << tag << "\">" << endl << endl;
AttributeList *attributes = getTagAttributes(tag);
stream << QuantaCommon::xmlFromAttributes(attributes);
stream << "</tag>" << endl
<< "</TAGS>" << endl;
file.close();
} else {
kdDebug(24000) << "Unable to write tag file: " << file.name() << endl;
}
}
KConfig config(dirName + "description.rc");
config.setGroup("General");
config.writeEntry("Name", TQFileInfo(m_dtdURL.fileName()).baseName()); //TODO: get from the DTD!
config.writeEntry("NickName", TQFileInfo(m_dtdURL.fileName()).baseName()); //TODO: get from the user!
config.sync();
}
bool DTD::parseDTD(const KURL &url)
{
TQString fileName = TQString();
if (!KIO::NetAccess::download(url, fileName))
{
KMessageBox::error(0, i18n("<qt>Cannot download the DTD from <b>%1</b>.</qt>").tqarg(url.prettyURL(0, KURL::StripFileProtocol)));
return false;
}
TQFile file(fileName);
if (file.open(IO_ReadOnly))
{
TQTextStream fileStream(&file);
fileStream.setEncoding(TQTextStream::UnicodeUTF8);
TQString entireDTD = fileStream.read();
file.close();
removeComments(entireDTD);
TQString line;
TQStringList lines = TQStringList::split("\n",entireDTD);
TQStringList::Iterator it = lines.begin();
while (it != lines.end()) {
line = *it;
if (line.startsWith("<")) {
while (!line.endsWith(">") && it != lines.end()) {
++it;
line += " \\end" + *it;
}
} else if (line.startsWith("%")) {
while (!line.endsWith(";") && it != lines.end()) {
++it;
line += *it;
}
}
line = line.stripWhiteSpace();
line = line.simplifyWhiteSpace();
//kdDebug(24000) << "Parsed line is: " << line << endl;
if ( line.startsWith("<!ENTITY") && line.endsWith(">"))
{
parseDTDEntity(line);
}
else
if (line.startsWith("<!ELEMENT") && line.endsWith(">"))
{
parseDTDElement(line);
}
else
if (line.startsWith("<!ATTLIST") && line.endsWith(">"))
{
parseDTDAttlist(line);
}
else
if (line.startsWith("%") && line.endsWith(";"))
{
line.remove(0,1);
line.truncate(line.length()-1);
KURL entityURL = url;
entityURL.setPath(url.directory()+ "/" + line + ".ent");
parseDTD(entityURL);
} else
{
kdDebug(24000) << TQString("Unknown tag: [%1]").tqarg(line) << endl;
}
if (it != lines.end()) ++it;
}
}
}
void DTD::parseDTDEntity(TQString line) {
TQString name;
TQString *value;
line.tqreplace("\\end", " ");
name = line.mid(11);
int firstSpace = name.tqfind(' ');
name = name.remove(firstSpace, name.length()-firstSpace);
value = new TQString(line.mid(11+firstSpace));
value->remove(0, value->tqfind("\"")+1);
value->remove(value->tqfindRev("\""), value->length());
parseDTDReplace(value);
stripSpaces(value);
entities.insert(name, value);
//kdDebug() << "Entity --- Name: " << name << " --- Value: " << *value << endl;
}
void DTD::parseDTDElement(const TQString &l) {
TQString name;
TQString *value;
TQString line = l;
line.tqreplace("\\end", " ");
name = line.mid(10);
int firstSpace = name.tqfind(' ');
name.remove(firstSpace, name.length()-firstSpace);
value = new TQString(line.mid(10+firstSpace));
//value->remove(0, value->tqfind("\"")+1);
value->remove(value->tqfind(">"), 10000);
parseDTDReplace(&name);
parseDTDReplace(value);
if ( name.startsWith("(") && name.endsWith(")") ) {
name.remove(0,1);
name.remove(name.length()-1,1);
TQStringList multipleTags = TQStringList::split("|", name);
TQStringList::Iterator it = multipleTags.begin();
while(it != multipleTags.end()) {
name = *it;
name = name.stripWhiteSpace();
elements.insert(name, value);
tags.append(name);
//kdDebug() << "Element --- Name: " << name << " --- Value: " << *value << endl;
++it;
}
} else {
elements.insert(name, value);
tags.append(name);
//kdDebug() << "Element --- Name: " << name << " --- Value: " << *value << endl;
}
}
void DTD::parseDTDAttlist(const TQString &l) {
TQString name;
TQString *value;
TQString line = l;
line.tqreplace("\\end", " ");
name = line.mid(10);
int firstSpace = name.tqfind(' ');
name.remove(firstSpace, name.length()-firstSpace);
value = new TQString(line.mid(10+firstSpace));
//value->remove(0, value->tqfind("\"")+1);
value->remove(value->tqfind(">"), 10000);
parseDTDReplace(&name);
parseDTDReplace(value);
if ( name.startsWith("(") && name.endsWith(")") ) {
name.remove(0,1);
name.remove(name.length()-1,1);
TQStringList multipleTags = TQStringList::split("|", name);
TQStringList::Iterator it = multipleTags.begin();
while(it != multipleTags.end()) {
name = *it;
name = name.stripWhiteSpace();
//elements.insert(name, value);
parseTagAttributeValues(name, value);
//kdDebug() << "Attlist --- Name: " << name << " --- Value: " << *value << endl;
++it;
}
} else {
//elements.insert(name, value);
parseTagAttributeValues(name, value);
//kdDebug() << "Attlist --- Name: " << name << " --- Value: " << *value << endl;
}
}
void DTD::parseTagAttributeValues(const TQString &name, TQString *value) {
AttributeList *attributes = new AttributeList();
TQStringList attrLines = TQStringList::split("\\end",*value);
TQStringList::Iterator lineIt = attrLines.begin();
while (lineIt != attrLines.end()) //iterate through the attribute lines
{
//split the attribute line
TQStringList all = TQStringList::split(" ", *lineIt);
TQStringList::Iterator it = all.begin();
while(it != all.end())
{
Attribute *attr = new Attribute();
attr->name = *it;
//kdDebug() << "Inserting for tag " << name << ": " << *it << endl;
++it;
TQString values = *it;
//list of possible values
if ( values.startsWith("(") && values.endsWith(")") )
{
values.remove(0,1);
values.remove(values.length()-1,1);
attr->values = TQStringList::split("|", values);
TQString s = (attr->values[0]+attr->values[1]).lower();
stripSpaces(&s);
if ((s == "truefalse") || (s == "falsetrue"))
{
attr->type = "check";
} else
{
attr->type = "list";
}
} else
{
attr->values = values;
attr->type = "input";
}
//kdDebug() << " --- values: " << *it << endl;
if (it != all.end())
{
++it;
TQString s=*it;
if (s.startsWith("\"") && s.endsWith("\"") && it!=all.end())
{
s.remove(0,1);
s.remove(s.length()-1,1);
attr->defaultValue = s;
}
if (s.startsWith("#") && it != all.end())
{
s.remove(0,1);
attr->status = s.lower();
}
if (*it == "#FIXED" && it != all.end())
{
++it;
attr->values.append(*it);
}
}
if (it != all.end())
{
++it;
}
attributes->append(attr);
}
++lineIt;
}
tagAttributes.insert(name, attributes);
}
void DTD::parseDTDReplace(TQString *value) {
int begin, end;
begin = value->tqfind("%");
end = value->tqfind(";");
while (begin != -1 && end != -1) {
TQString replaceText = value->mid(begin+1, end-begin-1);
TQString *replaceValue = entities.tqfind(replaceText);
if (replaceValue != 0L) {
value->tqreplace(begin, end-begin+1, *replaceValue);
} else {
kdDebug(24000) << "Can not find entity: " << replaceText << endl;
return;
}
begin = value->tqfind("%");
end = value->tqfind(";");
}
}
void DTD::stripSpaces(TQString *value) {
int index=-1;
while ( (index=value->tqfind(' ',++index)) != -1 ) {
if ( value->tqfindRev('(',index) != -1 && value->tqfind(')',index) != -1)
value->remove(index,1);
}
}
void DTD::removeComments(TQString &value) {
int begin, end;
begin = value.tqfind("<!--");
end = value.tqfind("-->",begin+2);
while (begin != -1 && end != -1) {
value.remove(begin, end-begin+3);
begin = value.tqfind("<!--");
end = value.tqfind("-->",begin+2);
}
begin = value.tqfind("--");
end = value.tqfind("--",begin+2);
while (begin != -1 && end != -1) {
value.remove(begin, end-begin+2);
begin = value.tqfind("--");
end = value.tqfind("--",begin+2);
}
value.tqreplace(TQRegExp("<!>"), "");
}
bool DTD::parseDTD()
{
return parseDTD(m_dtdURL);
}