# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1997
#
# Dateiname : p_sgml.py
# Datum : 03.11.1997
# letzte Änderung :
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Paket SGML, fasst alle SGML-Paket Klassen
# zusammen
#
# Anmerkungen :
#
# -------------------------------------------------------------
import c_sgmlquery
import c_sgmlread
import c_sgmlsearch
import c_sgmlstore
Klasse c_sgmlquery
# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1998
# Dateiname : c_sgmlquery.py
# Datum : 09.12.1997
# letzte Änderung :
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Eine Klasse die SGML spezifische Abfragen auf
# einem bestimmten Dokument durchfuehrt.
# Anmerkungen :
# -------------------------------------------------------------
#
# liefert das tagcount'e Tag mit Namen tagname zurueck
#
def sgmlquery_tag(self,tagname,tagcount):
query="select * from doc_tags where docnr="+str(self.ident)
query=query + " and contents ~* '"+tagname+"*' order by elementnr;"
res=self.pgconn.exec_query(query)
if res.get_tuple_count()>0:
return [ res.get_fieldvalue(tagcount-1,res.get_fieldindex_byname("contents")),res.get_fieldvalue(tagcount-1,res.get_fieldindex_byname("elementnr")) ]
else:
return ["",0]
#
# liefert den Inhalt des tagcount'en Tags
# mit Namen tagname zurueck
#
def sgmlquery_tagcontents(self,tagname,tagcount):
pos1=self.sgmlquery_tag(tagname,tagcount)[1]
query1="select contents,elementnr from doc_tags where docnr="+str(self.ident)
query1=query1 + " and elementnr>"+str(pos1)
query1=query1 +"and contents ~* '</"+tagname+"' order by elementnr;"
res1=self.pgconn.exec_query(query1)
if res1.get_tuple_count>0:
pos2=res1.get_fieldvalue(0,1)
query2= "select contents,elementnr from doc_elements* where docnr="
+str(self.ident)
query2=query2+" and elementnr>="+str(pos1)
query2=query2+" and elementnr<="+str(pos2)+" order by elementnr;"
res2=self.pgconn.exec_query(query2)
if res2.get_tuple_count>0:
j=res2.get_tuple_count()
i=0
erg=""
while i < j:
erg=erg+str(res2.get_fieldvalue(i,0))+"\n"
i=i+1
return erg[:-1]
else:
return ""
else:
return ""
#
# liefert den Strukturbaum als ASCII Text zurueck
#
def sgmlquery_structure(self):
query="select contents,elementnr from doc_tags where docnr="+ str(self.ident) + " order by elementnr;"
res=self.pgconn.exec_query(query)
j=res.get_tuple_count()
i=0
erg=""
while i < j:
erg=erg+str(res.get_fieldvalue(i,0))+"\n"
i=i+1
return erg[:-1]
#
# gibt das gesamte Dokument zurueck
#
def sgmlquery_doc(self):
query="select contents,elementnr from doc_elements* where docnr="+str(self.ident)+" order by elementnr;"
res=self.pgconn.exec_query(query)
j=res.get_tuple_count()
i=0
erg=""
while i < j:
erg=erg+str(res.get_fieldvalue(i,0))+"\n"
i=i+1
return erg
#
# gibt die Anzahl der Tags mit Namen tagname zurueck
#
def sgmlquery_tagcount(self,tagname):
query="select contents from doc_tags where docnr="+str(self.ident)+" and contents ~* '"+tagname+"';"
res=self.pgconn.exec_query(query)
return res.get_tuple_count()
#
# teilt ein gegebenes Tag (tagstr) in den Tagnamen
# und die einzelnen Attribute auf und liefert ein
# Dictionaries zurueck, dessen Schluessel die Attributnamen
# sind.
#
def sgmlquery_splittag(self,tagstr):
import string
ergdict={}
t=""
for j in range(len(tagstr)):
if tagstr[j]!="\012":
t=t+tagstr[j]
if pos3 == -1:
pos3=len(tagstr)
wert = string.strip( tagstr[:pos3] )
tagstr = tagstr[pos3+1:]
# attribute werte paar in dictionary einfuegen
ergdict[attrib]=wert
return ergdict
Klasse c_sgmlsearch
# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1998
# Dateiname : c_sgmlsearch.py
# Datum : 09.12.1997
# letzte Änderung : 15.01.1998
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Dies Klasse realisiert ein Suchinterface fuer
# in der Datenbank abgelegte SGML Dokumente
# Anmerkungen :
#
# -------------------------------------------------------------
# imports
import pgpy
class c_sgmlsearch:
#
# Konstruktor
#
def __init__(self):
# Verbindungsobjekt zur Datenbank instanziieren
self.conn=pgpy.pgconn(DL_PGHOST,DL_PGPORT,DL_DBNAME)
#
# Durchsucht alle in der Datenbank gespeicherten
# Tags nach searchstr und findet auch aehnliche
# Ausdruecke.
# Als Ergebnis wird eine ASCII Liste von Dokumenten ID's
# zurueckgegeben
#
def sgmlsearch_tag(self,searchstr):
# SQL Abfrage zusammenbauen
query="select * from doc_tags where contents ~*"+searchstr+";"
# Abfrage ausfuehren
res=self.conn.exec_query(query)
# Fehler aufgetreten ?
if res.get_tuple_count()==0:
# wenn ja, -1 zurueckgeben
return -1
else:
#wenn nein Ergebnis zurueckgeben
erg=res.get_resultlist(1,"|",1,0)
return erg
#
# Durchsucht die Text Klasse der Datenbank
# nach searchstr und findet auch aehnliche
# Ausdruecke.
# Als Ergebnis wird eine ASCII Liste von Dokumenten ID's
# zurueckgegeben
#
def sgmlsearch_text(self,searchstr):
# SQL Abfrage zusammenbauen
query="select * from doc_text where contents ~*"+searchstr+";"
# Abfrage ausfuehren
res=self.conn.exec_query(query)
# Fehler aufgetreten ?
if res.get_tuple_count()==0:
# wenn ja, -1 zurueckgeben
return -1
else:
#wenn nein Ergebnis zurueckgeben
erg=res.get_resultlist(1,"|",1,0)
return erg
#
# virtuelle Methode, muss in einer abgeleiteten
# Klasse ueberschrieben werden und ist zum Durchsuchen
# von Binaerdaten gedacht ;-)
#
def sgmlsearch_bin(self):
pass
#
# Durchsucht die Tag- und die Text- Klasse der Datenbank
# nach searchstr und findet auch aehnliche
# Ausdruecke.
# Als Ergebnis wird eine ASCII Liste von Dokumenten ID's
# zurueckgegeben.
#
def sgmlsearch_doc(self,searchstr):
erg=[]
erg1=self.sgmlsearch_tag(searchstr)
erg2=self.sgmlsearch_text(searchstr)
if erg1!=-1:
erg.append(erg1)
if erg2!=-1:
erg.append(erg2)
return erg
#
# ermittelt die Dokumenten-ID`s aller Dokumente, die der
# in dtdid gegebenen DTD entsprechen. Dabei kann dtdid
# die Public- oder die System-ID einer DTD angeben.
# Das Ergebnis wird in Form einer Lsite zurueckgeliefert.
#
def sgmlsearch_dtddocs(self,dtdid):
# DTD-Nummer ermitteln
query="select dtdnr from dtd where publicname ="+ dtdid + "or systemname =" +dtdid+";"
# Abfrage ausfuehren
res=self.conn.exec_query(query)
# Fehler aufgetreten ?
if res.get_tuple_count()==0:
# wenn ja, -1 zurueckgeben
return []
else:
#wenn nein Ergebnis zurueckgeben
dtdnr=res.get_fieldvalue(1,0)
# Doc-ID`s holen
query="select docnr from doc_description where dtdnr=" + str(dtdnr)+";"
# Abfrage ausfuehren
res=self.conn.exec_query(query)
# Fehler aufgetreten ?
if res.get_tuple_count()==0:
# wenn ja, -1 zurueckgeben
return []
else:
#wenn nein Ergebnis zurueckgeben
erg=res.get_resultlist(1,"|",1,0)
return erg
#
# ermittelt die Dokumenten-ID`s aller Dokumente, die
# der durch dtdid gegebenen DTD entsprechen und ein Tag
# enthalten das searchstr entspricht. Das Ergebnis wird
# in Form einer Liste zurueckgegeben.
#
def sgmlsearch_dtdandtags(self,dtdid,searchstr):
# ermittle Teilergebnisse
erg1=self.sgmlsearch_tag(searchstr)
erg2=self.sgmlsearch_dtddocs(dtdid)
erg=[]
for i in erg1:
if i in erg2:
erg.append(i)
return erg
Klasse c_sgmlstore
# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1998
# Dateiname : c_sgmlstore.py
# Datum : 09.12.1997
# letzte Änderung :
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Diese Klasse stellt Methoden bereit, um als
# Bitstrom vorliegende SGML-Dokumente in der
# Datenbank zu speichern
# Anmerkungen : Diese Klasse wird von der Klasse c_sgmlread
# abgeleitet. Die Varibalen DL_CURRENT_INFILE
# und DL_NEW_DOCID werden von der Ablauf-
# umgebung gesetzt.
# -------------------------------------------------------------
# Konstruktur der Basisklasse
c_sgmlread.c_sgmlread.__init__(self,self.infile)
# hole Liste der EMPTY Tags
self.dtdfname=class_funcs.get_dtdfile(self.get_dtd())
self.emptytags_lst=self.get_emptytags(self.dtdfname)
# baue Verbindung zu Postgres auf
self.conn=pgpy.pgconn(DL_PGHOST,DL_PGPORT,DL_DBNAME)
if self.conn.connstatus()!=0:
print "Postgresverbindung konnte nicht aufgebaut werden."
raise KeyboardInterrupt
#
# oeffnet den eingabebitstrom
#
def open_in(self):
self.fd_in=open(self.infile,"r")
#
# schliesst den Eingabebitstrom
#
def close_in(self):
self.fd_in.close()
#
# liest size Bytes vom Eingabebitstrom
#
def read_in(self,size):
return self.fd_in.read(size)
#
# setzt die aktuelle Position der Lese-/Schreibmarke
# des Eingabebitstroms (Syntax wie Python Befehl seek)
#
#
def seek_in(self,offset,whence):
self.fd_in.seek(offset,whence)
#
# liefert die aktuelle Position der Lese-/Schreibmarke
# des Eingabebitstroms zurueck
#
def tell_in(self):
return self.fd_in.tell()
#
# filtert in der Datenbank abzulegende Text, um sie an
# die PostgreSQL Syntax anzupassen
#
def pgfilter(self,fstr):
erg=""
for i in range(0,len(fstr)):
# ersetze anfuehrungszeichen
if fstr[i]=="'":
erg=erg+"\\"
erg=erg+fstr[i]
return erg
#
# liefert eine Liste alle in der DTD fname definierten
# EMPTY-Tags zurueck
#
def get_emptytags(self,fname):
import c_bsio
import string
fd=c_bsio.c_bsio(fname,"r")
erglst=[]
fd.open()
buff = " "
while buff!="":
buff=fd.readline()
if string.upper(string.strip(buff)[:9])=="<!ELEMENT":
if string.find(buff,"EMPTY")!=-1:
erglst.append(string.upper( string.strip(buff)[10:string.find( string.strip(buff),"-")-1]))
fd.close()
return erglst
#
# vermerkt in der Datenbank, dass das Dokument in der Datenbank
# gespeichert wurde
#
def register_sgmlstore(self):
query="update doc_description set sgml_stored='t' where docnr="
query=query+str(self.docid)+";"
res=self.conn.exec_query(query)
if res.commandstatus()[0:6]!="UPDATE":
print "Fehler bei Update in register_sgmlstore"
return -1
else:
return 0
#
# vermerkt die DTD der das Dokument angehoerig ist in
# der Datenbank
#
def save_doctype(self):
dtdtup=self.get_dtd()
dtdnum=class_funcs.get_dtdnum(dtdtup)
query="update doc_description set dtdnr="
query=query+str(res.get_fieldvalue(1,0))
query=query+" where docnr="+str(self.docid)+";"
res=self.conn.exec_query(query)
if res.commandstatus[0:6]!="UPDATE":
print "Fehler c_sgmlstore.save_doctype beim Eintragen der DTDNR"
#
# speichert tagst in der Tag-Klasse der Datenbank
# und berechnet die Strukturbaumverweise automatisch
#
def save_astag(self,tagstr):
dbclass="doc_tags"
self.element_counter=self.element_counter+1
if self.ntag[0:2]!="</":
self.ntyp="S"
self.stack.append((self.ntag,self.nnum))
else:
self.ntyp="E"
self.ls=self.stack[-1]
self.stack=self.stack[:-1]
if self.ntyp=="S" and self.atyp=="S":
# atag ist Vater von ntag
query="update doc_tags set son="+str(self.nnum)
query=query+" where docnr="+str(self.docid)
query=query+" and elementnr="+str(self.anum)+";"
res=self.conn.exec_query(query)
if res.commandstatus()[0:6]!="UPDATE":
print "FEHLER in c_sgmlstore.save_astag Query 1"
if self.ntyp=="S" and self.atyp=="E":
# ntag ist rechter Bruder von anum
query="update doc_tags set brother="+str(self.nnum)
query=query+" where docnr="+str(self.docid)
query=query+" and elementnr="+str(self.anum)+";"
res=self.conn.exec_query(query)
if res.commandstatus()[0:6]!="UPDATE":
print "FEHLER in c_sgmlstore.save_astag Query 2"
if self.ntyp=="E" and self.atyp=="S":
# atag ist ein Blatt
query="update doc_tags set brother="+str(self.nnum)
query=query+" where docnr="+str(self.docid)
query=query+" and elementnr="+str(self.anum)+";"
res=self.conn.exec_query(query)
if res.commandstatus()[0:6]!="UPDATE":
print "FEHLER in c_sgmlstore.save_astag Query 3"
if self.ntyp=="E" and self.atyp=="E":
# atag ist ein Blatt
query="update doc_tags set brother="+str(self.nnum)
query=query+" where docnr="+str(self.docid)
query=query+" and elementnr="+str(self.ls[1])+";"
res=self.conn.exec_query(query)
if res.commandstatus()[0:6]!="UPDATE":
print "FEHLER in c_sgmlstore.save_astag Query 4"
# letztes Tag und Typ merken
self.atag=self.ntag
self.anum=self.nnum
if isempty==0:
self.atyp=self.ntyp
elif isempty==1:
self.atyp="E"
self.stack=self.stack[:-1]
# neuen Tagdatensatz in DB eintragen
tagstr=self.pgfilter(tagstr)
query="insert into "+dbclass+" values ("+str(self.docid)+","
query=query+str(self.nnum)+",0,0,'"+tagstr+"',"
query=query+str(0)+");"
res=self.conn.exec_query(query)
if res.commandstatus()[0:6]!="INSERT":
print "FEHLER in c_sgmlstore.save_astag Query 5"
#
# speichert textstr in der Text-Klasse der Datenbank
#
def save_astext(self,textstr):
dbclass="doc_text"
self.element_counter=self.element_counter+1
textstr=self.pgfilter(textstr)
query="insert into "+dbclass+" values ("+str(self.docid)+","
query=query+str(self.element_counter)+",0,0,'"+textstr+"');"
res=self.conn.exec_query(query)
erg=res.commandstatus()
if str(erg)[0:6]!="INSERT":
print "Fehler bei INSERT in Postgres"
raise KeyboardInterrupt
return 0
#
# speichert das unter der URL urlstr abrufbare Objekt
# als binaere Daten in der Datenbank
#
def save_asbin(self,urlstr):
dbclass="doc_bin"
self.element_counter=self.element_counter+1
binstr=urllib.urlretrieve(urlstr)
query="insert into "+dbclass+" values ("+str(self.docid)+","
query=query+str(self.element_counter)+",0,0,'"+binstream+"');"
res=self.conn.exec_query(query)
erg=res.commandstatus()
if str(erg)[0:6]!="INSERT":
print "Fehler bei INSERT in Postgres"
raise KeyboardInterrupt
return 0
#
# liest das naechste Tag aus dem Eingabebitstrom und
# gibt es zurueck
#
def get_nextelement(self):
# leerzeilen ueberspringen
test1=""
test1=self.read(1)
while test1=="\n":
test1=self.read(1)
# position des Lese-/Schreibmarke korrigieren
if test1!="":
if self.tell()>1:
self.seek(-1,1)
# sicherstellen das nicht mitten im Tag gesucht wird
if test1=="<":
return self.get_nexttag()
else:
erg=""
buff=" "
while buff!="<" and buff!="":
buff=self.read(1)
erg=erg+buff
# letztes Zeichen wegwerfen
if len(erg)>1:
erg=erg[0:-1]
# position des Lese-/Schreibmarke korrigieren
self.seek(-1,1)
return erg
else:
return ""
#
# ermittelt, ob es sich bei tagstr um ein Tag handelt
# gibt 1 zureuck wenn ja, 0 wenn nein und -1 bei Fehler
#
def is_tag(self,tagstr):
if len(tagstr)!=0:
if tagstr[0]=="<" and tagstr[len(tagstr)-1]==">":
return 1
else:
return 0
else:
return -1
#
# ermittelt, ob es sich bei tagstr um ein Empty-Tag handelt
# gibt 1 zureuck wenn ja, 0 wenn nein und -1 bei Fehler
#
def is_emptytag(self,tagstr):
import string
if len(tagstr)!=0:
if tagstr[1:string.find(tagstr," ")] in self.emptytags_lst:
return 1
else:
return 0
else:
return -1