* doc/grampsxml.dtd: Add to CVS (replaces gramps.dtd).

* src/WriteXML.py: Bring in sync with the DTD:
  + add PUBLIC declaration of the DTD file
  + remove db stats as attributes of the database element
  + prepend all handles and hlinks with "_" (conform to XML ID)
  + replace "aka" with "name", "name" with "name preferred=1"


svn: r5272
This commit is contained in:
Alex Roitman 2005-10-05 23:50:10 +00:00
parent a0a164621b
commit 028fc7266b
3 changed files with 40 additions and 346 deletions

View File

@ -1,3 +1,11 @@
2005-10-05 Alex Roitman <shura@gramps-project.org>
* doc/grampsxml.dtd: Add to CVS (replaces gramps.dtd).
* src/WriteXML.py: Bring in sync with the DTD:
+ add PUBLIC declaration of the DTD file
+ remove db stats as attributes of the database element
+ prepend all handles and hlinks with "_" (conform to XML ID)
+ replace "aka" with "name", "name" with "name preferred=1"
2005-10-05 Julio Sanchez <jsanchez@users.sourceforge.net>
* src/plugins/ReorderIds.py: handle more cases correctly

View File

@ -1,320 +0,0 @@
<!--?xml version="1.0" encoding="UTF-8"?-->
<!-- A Document Type Definition for genealogy data (as produced by Gramps)
Copyright (c) 2001 Graham J. Williams
Time-stamp: <2002/01/22 15:41:37 Graham.Williams@csiro.au>
Freely Redistributable under the terms of the GNU General Public License.
Based on GEDCOM and conforming to the Gramps XML encoding.
Still under development and Gramps XML not complete.
Information on Gramps is available from http://
-->
<!--
DATABASE
Defines an XML document which is a <database> consisting of a
header Information about the "owner" of the database
people
families
sources
places
objects
bookmarks
-->
<!ELEMENT database (header, people?, families?, sources?, places?, objects?,
bookmarks?)>
<!-- ************************************************************
HEADER
A <header> consists of <created> (information about this
genealogical database) and <researcher> (information about the
person who created this genealogical database)
-->
<!ELEMENT header (created, researcher?)>
<!ELEMENT created EMPTY>
<!ATTLIST created
date CDATA #REQUIRED
version CDATA #REQUIRED
people CDATA #REQUIRED
families CDATA #REQUIRED>
<!ELEMENT researcher (resname, resaddr?, rescity?, resstate?,
rescountry?, respostal?, resphone?, resemail?)>
<!ELEMENT resname (#PCDATA)>
<!ELEMENT resaddr (#PCDATA)>
<!ELEMENT rescity (#PCDATA)>
<!ELEMENT resstate (#PCDATA)>
<!ELEMENT rescountry (#PCDATA)>
<!ELEMENT respostal (#PCDATA)>
<!ELEMENT resphone (#PCDATA)>
<!ELEMENT resemail (#PCDATA)>
<!-- ************************************************************
PEOPLE
The UID is a place holder for PAF UID's that are imported. PAF
generates a unique ID for each person which is useful for
merges. It is not used by Gramps otherwise.
-->
<!ELEMENT people (person)*>
<!ATTLIST people default CDATA #IMPLIED>
<!--
PERSON
gender Either M or F.
name
aka Also known as. Alternative names from marriage,
adoption, legal name change, etc
nick The nick name - a name the person is sometimes known by.
-->
<!ELEMENT person (gender, name?, aka*, nick?, pos?, uid?, event*,
objref*, url*, childof*, address*, parentin*,
sourceref?, attribute*, note?)>
<!ATTLIST person id ID #REQUIRED>
<!--
GENDER has values of M or F.
-->
<!ELEMENT gender (#PCDATA)>
<!--
NAME and AKA
first Given names
last Surname
suffix
title E.g., Sargent Major
-->
<!ELEMENT name (first?, last?,suffix?,title?)>
<!ATTLIST name conf CDATA #IMPLIED
priv CDATA #IMPLIED>
<!ELEMENT aka (first?, last?,suffix?,note?)>
<!ATTLIST aka conf CDATA #IMPLIED
priv CDATA #IMPLIED>
<!ELEMENT first (#PCDATA)>
<!ELEMENT last (#PCDATA)>
<!ELEMENT suffix (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT nick (#PCDATA)>
<!ELEMENT uid (#PCDATA)>
<!ELEMENT pos EMPTY>
<!ATTLIST pos x CDATA #REQUIRED
y CDATA #REQUIRED>
<!ELEMENT childof EMPTY>
<!ATTLIST childof
ref IDREF #REQUIRED
mrel (Birth|Adopted|Stepchild|Other|Unknown) #IMPLIED
frel (Birth|Adopted|Stepchild|Other|Unknown) #IMPLIED>
<!ELEMENT parentin EMPTY>
<!ATTLIST parentin
ref IDREF #REQUIRED>
<!ELEMENT address (dateval?,street?,city?,state?,country?,postal?,
note?,sourceref?)>
<!ATTLIST address conf CDATA #IMPLIED
priv CDATA #IMPLIED>
<!ELEMENT street (#PCDATA)>
<!ELEMENT city (#PCDATA)>
<!ELEMENT country (#PCDATA)>
<!ELEMENT postal (#PCDATA)>
<!ELEMENT state (#PCDATA)>
<!-- ************************************************************
FAMILY
An element to record information about a family.
-->
<!ELEMENT families (family)*>
<!ELEMENT family (father?,mother?,event*,objref*,child*,attribute*,note?)>
<!ATTLIST family
id ID #REQUIRED
type (Married|Unmarried|Partners|Other|Unkown) #IMPLIED>
<!ELEMENT father EMPTY>
<!ATTLIST father ref IDREF #REQUIRED>
<!ELEMENT mother EMPTY>
<!ATTLIST mother ref IDREF #REQUIRED>
<!ELEMENT child EMPTY>
<!ATTLIST child ref IDREF #REQUIRED>
<!-- ************************************************************
SOURCES
-->
<!ELEMENT sources (source)*>
<!ELEMENT source (sauthor?,spubinfo?,scallno?)>
<!ATTLIST source id ID #REQUIRED>
<!ELEMENT sauthor (#PCDATA)>
<!ELEMENT spubinfo (#PCDATA)>
<!ELEMENT scallno (#PCDATA)>
<!-- ************************************************************
PLACES
-->
<!ELEMENT places (placeobj)*>
<!ELEMENT placeobj (coord?,location*,objref*,url*,note?)>
<!ATTLIST placeobj id ID #REQUIRED title CDATA #IMPLIED>
<!ELEMENT coord EMPTY>
<!ATTLIST coord long CDATA #REQUIRED lat CDATA #REQUIRED>
<!ELEMENT location EMPTY>
<!ATTLIST location
city CDATA #IMPLIED
county CDATA #IMPLIED
state CDATA #IMPLIED
country CDATA #IMPLIED
parish CDATA #IMPLIED
>
<!ELEMENT objects (object)*>
<!ELEMENT object (attribute)*>
<!ATTLIST object
id ID #REQUIRED
src CDATA #IMPLIED
mime CDATA #IMPLIED
description CDATA #IMPLIED>
<!-- ************************************************************
BOOKMARKS
-->
<!ELEMENT bookmarks (bookmark)*>
<!ELEMENT bookmark EMPTY>
<!ATTLIST bookmark ref IDREF #REQUIRED>
<!-- ************************************************************
SHARED ELEMENTS
-->
<!ELEMENT attribute (note?,sourceref?)>
<!ATTLIST attribute conf CDATA #IMPLIED
priv CDATA #IMPLIED
type CDATA #IMPLIED
value CDATA #IMPLIED
>
<!--ELEMENT attr_type (#PCDATA)>
<!ELEMENT attr_value (#PCDATA)-->
<!--
EVENT
We can enumerate all possibilities for an event and then this will
not conform to Gramps as Gramps allows any type of events (i.e., a
user can define their own type of event) . By allowing anything
(CDATA) we no longer have automatic checking and in emacs no more
automatic selection of event types.
So decide to use the enumerated list for now unless there is a storm
of protest.
Alternative Birth Another possible birth date
Degree Awarding of a degree
Education Some step in the education process
Graduation Graduation (often same as degree)
-->
<!ELEMENT event (dateval?,place?,description?,sourceref?,note?)>
<!ATTLIST event type
(Annulment|Birth|Death|Christening|Baptism|Engagement|Marriage|
Occupation|Education|Degree|Immi|Burial|Cremation)
#REQUIRED>
<!ELEMENT dateval EMPTY>
<!ATTLIST dateval
val CDATA #REQUIRED
type CDATA #IMPLIED>
<!--ELEMENT date (#PCDATA) replaced by dateval-->
<!ELEMENT description (#PCDATA)>
<!ELEMENT note (#PCDATA)>
<!ELEMENT url EMPTY>
<!ATTLIST url href CDATA #REQUIRED
conf CDATA #IMPLIED
priv (0|1) #IMPLIED
description CDATA #IMPLIED>
<!ELEMENT place EMPTY>
<!ATTLIST place ref IDREF #REQUIRED>
<!ELEMENT sourceref (spage?,scomments?,stext?,sdate?)>
<!ATTLIST sourceref ref IDREF #REQUIRED>
<!ELEMENT spage (#PCDATA)>
<!ELEMENT scomments (#PCDATA)>
<!ELEMENT sdate (#PCDATA)>
<!ELEMENT stext (#PCDATA)>
<!ELEMENT objref (attribute)*>
<!ATTLIST objref
ref IDREF #REQUIRED
>
<!ELEMENT img EMPTY>
<!ATTLIST img
src CDATA #REQUIRED
description CDATA #IMPLIED
display CDATA #IMPLIED>

View File

@ -65,6 +65,9 @@ try:
except:
_gzip_ok = 0
_xml_version = "1.0.0"
#-------------------------------------------------------------------------
#
#
@ -205,16 +208,17 @@ class XmlWriter:
total = person_len + family_len + place_len + source_len
self.g.write('<?xml version="1.0" encoding="UTF-8"?>\n')
self.g.write('<!DOCTYPE database SYSTEM "gramps.dtd" []>\n')
self.g.write("<database xmlns=\"http://gramps.sourceforge.net/database\">\n")
self.g.write('<!DOCTYPE database '
'PUBLIC "-//GRAMPS//DTD GRAMPS XML V%s//EN"\n'
'"http://gramps-project.org/xml/%s/grampsxml.dtd">\n'
% (_xml_version,_xml_version))
self.g.write("<database xmlns=\"http://gramps-project.org/\">\n")
self.g.write(" <header>\n")
self.g.write(" <created date=\"%s %s %s\"" % \
(date[2],date[1].upper(),date[4]))
self.g.write(" version=\"" + const.version + "\"")
self.g.write(" people=\"%d\"" % person_len)
self.g.write(" families=\"%d\"" % family_len)
self.g.write(" sources=\"%d\"" % source_len)
self.g.write(" places=\"%d\"/>\n" % place_len)
self.g.write("/>\n")
self.g.write(" <researcher>\n")
self.write_line("resname",owner.get_name(),3)
self.write_line("resaddr",owner.get_address(),3)
@ -236,7 +240,7 @@ class XmlWriter:
if person:
self.g.write(' default="%s" home="%s"' %
(person.get_gramps_id (),
person.get_handle()))
"_"+person.get_handle()))
self.g.write(">\n")
keys = self.db.get_person_handles(sort_handles=False)
@ -259,9 +263,9 @@ class XmlWriter:
self.write_line("gender","F",3)
else:
self.write_line("gender","U",3)
self.dump_name("name",person.get_primary_name(),3)
self.dump_name(person.get_primary_name(),True,3)
for name in person.get_alternate_names():
self.dump_name("aka",name,3)
self.dump_name(name,False,3)
self.write_line("nick",person.get_nick_name(),3)
birth = self.db.get_event_from_handle(person.get_birth_handle())
@ -307,7 +311,7 @@ class XmlWriter:
else:
frel=''
self.g.write(" <childof hlink=\"%s\"%s%s/>\n" % \
(alt[0], mrel, frel))
("_"+alt[0], mrel, frel))
for family_handle in person.get_family_handle_list():
self.write_ref("parentin",family_handle,3)
@ -369,7 +373,7 @@ class XmlWriter:
self.callback(float(count)/float(total))
count = count + 1
self.g.write(" <source id=\"%s\" handle=\"%s\" change=\"%d\">\n" %
(source.get_gramps_id(), source.get_handle(),
(source.get_gramps_id(), "_"+source.get_handle(),
source.get_change_time()))
self.write_force_line("stitle",source.get_title(),3)
self.write_line("sauthor",source.get_author(),3)
@ -415,7 +419,7 @@ class XmlWriter:
if len(self.db.get_bookmarks()) > 0:
self.g.write(" <bookmarks>\n")
for person_handle in self.db.get_bookmarks():
self.g.write(' <bookmark hlink="%s"/>\n' % person_handle)
self.g.write(' <bookmark hlink="%s"/>\n' % ("_"+person_handle))
self.g.write(" </bookmarks>\n")
if len(self.db.name_group) > 0:
@ -472,7 +476,7 @@ class XmlWriter:
sp = " "*index
com = self.fix(w.get_comment())
if w.get_type() == RelLib.Event.ID:
self.g.write('%s<witness hlink="%s">\n' % (sp,w.get_value()))
self.g.write('%s<witness hlink="%s">\n' % (sp,"_"+w.get_value()))
if com:
self.g.write(' %s<comment>%s</comment>\n' % (sp,com))
self.g.write('%s</witness>\n' % sp)
@ -521,7 +525,7 @@ class XmlWriter:
self.g.write('%s<status val="%d"/>\n' % (sp2,ord.get_status()))
if ord.get_family_handle():
self.g.write('%s<sealed_to hlink="%s"/>\n' %
(sp2,self.fix(ord.get_family_handle())))
(sp2,"_"+self.fix(ord.get_family_handle())))
if ord.get_note() != "":
self.write_note("note",ord.get_note_object(),index+1)
for s in ord.get_source_references():
@ -538,12 +542,12 @@ class XmlWriter:
q = source_ref.get_confidence_level()
self.g.write(" " * index)
if p == "" and c == "" and t == "" and d.is_empty() and q == 2:
self.g.write('<sourceref hlink="%s"/>\n' % source.get_handle())
self.g.write('<sourceref hlink="%s"/>\n' % ("_"+source.get_handle()))
else:
if q == 2:
self.g.write('<sourceref hlink="%s">\n' % source.get_handle())
self.g.write('<sourceref hlink="%s">\n' % ("_"+source.get_handle()))
else:
self.g.write('<sourceref hlink="%s" conf="%d">\n' % (source.get_handle(),q))
self.g.write('<sourceref hlink="%s" conf="%d">\n' % ("_"+source.get_handle(),q))
self.write_line("spage",p,index+1)
self.write_text("scomments",c,index+1)
self.write_text("stext",t,index+1)
@ -552,12 +556,12 @@ class XmlWriter:
def write_ref(self,label,gid,index=1):
if gid:
self.g.write('%s<%s hlink="%s"/>\n' % (" "*index,label,gid))
self.g.write('%s<%s hlink="%s"/>\n' % (" "*index,label,"_"+gid))
def write_id(self,label,person,index=1):
if person:
self.g.write('%s<%s id="%s" handle="%s" change="%d"' %
(" "*index,label,person.get_gramps_id(),person.get_handle(),
(" "*index,label,person.get_gramps_id(),"_"+person.get_handle(),
person.get_change_time()))
comp = person.get_complete_flag()
if comp:
@ -570,7 +574,7 @@ class XmlWriter:
comp = family.get_complete_flag()
sp = " " * index
self.g.write('%s<family id="%s" handle="%s" change="%d"' %
(sp,family.get_gramps_id(),family.get_handle(),family.get_change_time()))
(sp,family.get_gramps_id(),"_"+family.get_handle(),family.get_change_time()))
if comp:
self.g.write(' complete="1"')
if rel != "":
@ -647,10 +651,12 @@ class XmlWriter:
if value != None:
self.g.write('%s<%s>%s</%s>\n' % (' '*indent,label,self.fix(value),label))
def dump_name(self,label,name,index=1):
def dump_name(self,name,preferred=False,index=1):
sp = " "*index
name_type = name.get_type()
self.g.write('%s<%s' % (sp,label))
self.g.write('%s<name' % sp)
if preferred:
self.g.write(' preferred="1"')
if name_type:
self.g.write(' type="%s"' % name_type)
if name.get_privacy() != 0:
@ -672,7 +678,7 @@ class XmlWriter:
for s in name.get_source_references():
self.dump_source_ref(s,index+1)
self.g.write('%s</%s>\n' % (sp,label))
self.g.write('%s</name>\n' % sp)
def append_value(self,orig,val):
if orig:
@ -750,7 +756,7 @@ class XmlWriter:
sp = ' '*indent
for photo in list:
mobj_id = photo.get_reference_handle()
self.g.write('%s<objref hlink="%s"' % (sp,mobj_id))
self.g.write('%s<objref hlink="%s"' % (sp,"_"+mobj_id))
if photo.get_privacy():
self.g.write(' priv="1"')
proplist = photo.get_attribute_list()
@ -799,7 +805,7 @@ class XmlWriter:
title = self.fix(self.build_place_title(place.get_main_location()))
self.g.write(' <placeobj id="%s" handle="%s" change="%d" title="%s"' %
(handle,place.get_handle(),place.get_change_time(),title))
(handle,"_"+place.get_handle(),place.get_change_time(),title))
if longitude or lat or not ml_empty or llen > 0 or note:
self.g.write('>\n')
@ -828,7 +834,7 @@ class XmlWriter:
if self.strip_photos:
path = os.path.basename(path)
self.g.write(' <object id="%s" handle="%s" change="%d" src="%s" mime="%s"' %
(handle,obj.get_handle(),obj.get_change_time(),path,mime_type))
(handle,"_"+obj.get_handle(),obj.get_change_time(),path,mime_type))
self.g.write(' description="%s"' % self.fix(obj.get_description()))
alist = obj.get_attribute_list()
note = obj.get_note()