Source for file Genealogy_Parser.php
Documentation is available at Genealogy_Parser.php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Olivier Vanhoucke <olivier@php.net> |
// +----------------------------------------------------------------------+
// $Id: Genealogy_Parser.php,v 1.2 2003/01/04 11:54:56 mj Exp $
require_once 'Individual.php';
require_once 'Family.php';
require_once 'Object.php';
require_once 'Header.php';
* @author Olivier Vanhoucke <olivier@php.net>
* @version $Revision: 1.2 $
* @package Genealogy_Gedcom
* Contains Gedcom filename
* Contains all lines of the Gedcom file
var $_FileContent = array ();
* Contains the all tree of the file contain
var $_GedcomTree = array ();
* Contains the header tree
var $_GedcomHeaderTree = array ();
* Contains the individuals tree
var $_GedcomIndividualsTree = array ();
* Contains the families tree
var $_GedcomFamiliesTree = array ();
* Contains the objects tree
var $_GedcomObjectsTree = array ();
* Contains an array of Genealogy_Individual object
var $GedcomIndividualsTreeObjects = array ();
* Contains an array of Genealogy_Family object
var $GedcomFamiliesTreeObjects = array ();
* Contains an array of Genealogy_Object object
var $GedcomObjectsTreeObjects = array ();
* Contains a Genealogy_Header object
var $GedcomHeaderTreeObject = array ();
* @return string error message
function _raiseError ($msg) {
PEAR ::raiseError ('<b>Genealogy_Parser Error : </b>'. $msg, null , PEAR_ERROR_DIE );
* Launch parsing (use in Genealogy_Gedcom constructor)
$this->_getFileContent ();
if ($this->_isValidGedcomFile ()) {
$this->_makeGedcomTree ();
$this->_parseIndividuals ();
unset ($this->_FileContent);
unset ($this->_GedcomTree);
unset ($this->_GedcomHeaderTree);
Genealogy_Parser ::_raiseError ($this->_GedcomFile. ' is not a valid Gedcom file.');
* Read Gedcom file contains
function _getFileContent () {
if ($fp = @fopen($this->_GedcomFile, 'r')) {
// unset the last line if it's empty
if (empty ($buffer[count($buffer) - 1 ])) {
unset ($buffer[count($buffer) - 1 ]);
$this->_FileContent = $buffer;
Genealogy_Parser ::_raiseError ('Cannot open file '. $this->_GedcomFile);
* Test if it's a valid gedcom file
function _isValidGedcomFile () {
return (($this->_FileContent[0 ] == '0 HEAD') && ($this->_FileContent[count($this->_FileContent) - 1 ] == '0 TRLR')) ? true : false;
* $gedcom = array('0 xxx', '1 yyy', '2 zzz', '0 xxx', '1 yyy');
* $tree = array(array('0 xxx', '1 yyy', '2 zzz'),
* array('0 xxx', '1 yyy')
function _makeGedcomTree () {
foreach ($this->_FileContent as $element) {
if ($element{0 } == '0') {
$this->_GedcomTree[$i] = array ();
$this->_GedcomTree[$i][] = $element;
* Separate Gedcom tree in 4 parts : gedcom file header, individuals, families, objects.
/* could replace \d* -> 0 */
foreach ($this->_GedcomTree as $element) {
if (@preg_match('/0 @I\d*@ INDI/US', $element[0 ])) {
$this->_GedcomIndividualsTree[] = $element;
if (@preg_match('/0 @F\d*@ FAM/US', $element[0 ])) {
$this->_GedcomFamiliesTree[] = $element;
if (@preg_match('/0 @O\d*@ OBJE/US', $element[0 ])) {
$this->_GedcomObjectsTree[] = $element;
* Parse Gedcom file header
* Create a Genealogy_Header object
function _parseHeader () {
$this->_GedcomHeaderTree = $this->_GedcomTree[0 ];
$Genealogy_Header_Param = array (@preg_replace('/\d VERS (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'GEDC', 'VERS')]),
@preg_replace('/\d FORM (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'GEDC', 'FORM')]),
@preg_replace('/\d DATE (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_tag ($this->_GedcomHeaderTree, 'DATE')]),
@preg_replace('/\d TIME (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'DATE', 'TIME')]),
@preg_replace('/\d NAME (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'NAME')]),
@preg_replace('/\d VERS (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'VERS')]),
@preg_replace('/\d CORP (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'CORP')]),
@preg_replace('/\d ADDR (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'ADDR')]),
@preg_replace('/\d ADR1 (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'ADR1')]),
@preg_replace('/\d ADR2 (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'ADR2')]),
@preg_replace('/\d CITY (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'CITY')]),
@preg_replace('/\d POST (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'POST')]),
@preg_replace('/\d CTRY (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'CTRY')]),
@preg_replace('/\d PHON (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'PHON')]),
@preg_replace('/\d DATA (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_subTag ($this->_GedcomHeaderTree, 'SOUR', 'DATA')]),
@preg_replace('/\d OBJE @(O\d*)@/US', '$1', $this->_GedcomHeaderTree[$this->_tag ($this->_GedcomHeaderTree, 'OBJE')]),
@preg_replace('/\d LANG (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_tag ($this->_GedcomHeaderTree, 'LANG')]),
@preg_replace('/\d CHAR (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_tag ($this->_GedcomHeaderTree, 'CHAR')]),
@preg_replace('/\d COPR (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_tag ($this->_GedcomHeaderTree, 'COPR')]),
@preg_replace('/\d FILE (.*)/US', '$1', $this->_GedcomHeaderTree[$this->_tag ($this->_GedcomHeaderTree, 'FILE')]),
@preg_replace('/\d NAME (.*)/US', '$1', $this->_GedcomTree[1 ][$this->_subTag ($this->_GedcomTree[1 ], 'SUBM', 'NAME')]),
@preg_replace('/\d NOTE (.*)/US', '$1', $this->_GedcomTree[1 ][$this->_subTag ($this->_GedcomTree[1 ], 'SUBM', 'NOTE')]),
$this->_contTag ($this->_GedcomTree[1 ], 'ADDR'),
@preg_replace('/\d PHON (.*)/US', '$1', $this->_GedcomTree[1 ][$this->_subTag ($this->_GedcomTree[1 ], 'SUBM', 'PHON')])
unset ($Genealogy_Header_Param);
* Create an array of Genealogy_Individual object
function _parseIndividuals () {
for ($i=0; $i < count($this->_GedcomIndividualsTree); $i++ ) {
$Genealogy_Individual_Param = array (@preg_replace('/0 @(I\d*)@ INDI/US', '$1', $this->_GedcomIndividualsTree[$i][0 ]),
@preg_replace('/\d NAME (.*)\/(.*)\//US', '$2', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'NAME')]),
@preg_replace('/\d NAME (.*)\/(.*)\//US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'NAME')]),
@preg_replace('/\d NICK (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'NICK')]),
@preg_replace('/\d TITL (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'TITL')]),
@preg_replace('/\d DATE (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'BIRT', 'DATE')]),
@preg_replace('/\d PLAC (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'BIRT', 'PLAC')]),
@preg_replace('/\d SOUR (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'BIRT', 'SOUR')]),
@preg_replace('/\d NOTE (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'BIRT', 'NOTE')]),
@preg_replace('/\d DATE (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'DEAT', 'DATE')]),
@preg_replace('/\d PLAC (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'DEAT', 'PLAC')]),
@preg_replace('/\d SOUR (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'DEAT', 'SOUR')]),
@preg_replace('/\d NOTE (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'DEAT', 'NOTE')]),
@preg_replace('/\d SEX (\w)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'SEX')]),
@preg_replace('/\d OCCU (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'OCCU')]),
@preg_replace('/\d SOUR (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'SOUR')]),
@preg_replace('/\d OBJE @(O\d*)@/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'OBJE')]),
$this->_arrayTag ($this->_GedcomIndividualsTree[$i], 'FAMS'),
@preg_replace('/\d FAMC @(F\d*)@/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'FAMC')]),
@preg_replace('/\d NATI (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'NATI')]),
@preg_replace('/\d DATE (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'FCOM', 'DATE')]),
@preg_replace('/\d PLAC (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'FCOM', 'PLAC')]),
@preg_replace('/\d SOUR (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'FCOM', 'SOUR')]),
@preg_replace('/\d NOTE (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'FCOM', 'NOTE')]),
@preg_replace('/\d DATE (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'BURI', 'DATE')]),
@preg_replace('/\d PLAC (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_subTag ($this->_GedcomIndividualsTree[$i], 'BURI', 'PLAC')]),
@preg_replace('/\d NOTE (.*)/US', '$1', $this->_GedcomIndividualsTree[$i][$this->_tag ($this->_GedcomIndividualsTree[$i], 'NOTE')])
unset ($Genealogy_Individual_Param);
* Create an array of Genealogy_Family object
function _parseFamilies () {
for ($i=0; $i < count($this->_GedcomFamiliesTree); $i++ ) {
$Genealogy_Family_Param = array (@preg_replace('/0 @(F\d*)@ FAM/US', '$1', $this->_GedcomFamiliesTree[$i][0 ]),
@preg_replace('/\d HUSB @(I\d*)@/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_tag ($this->_GedcomFamiliesTree[$i],'HUSB')]),
@preg_replace('/\d WIFE @(I\d*)@/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_tag ($this->_GedcomFamiliesTree[$i],'WIFE')]),
@preg_replace('/\d NCHI (.*)/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_tag ($this->_GedcomFamiliesTree[$i],'NCHI')]),
$this->_arrayTag ($this->_GedcomFamiliesTree[$i], 'CHIL'),
@preg_replace('/\d DATE (.*)/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_subTag ($this->_GedcomFamiliesTree[$i],'MARR', 'DATE')]),
@preg_replace('/\d TIME (.*)/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_subTag ($this->_GedcomFamiliesTree[$i],'MARR', 'TIME')]),
@preg_replace('/\d PLAC (.*)/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_subTag ($this->_GedcomFamiliesTree[$i],'MARR', 'PLAC')]),
$this->_arrayWitnessTag ($this->_GedcomFamiliesTree[$i]),
$this->_contTag ($this->_GedcomFamiliesTree[$i], 'NOTE'),
@preg_replace('/\d SOUR (.*)/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_subTag ($this->_GedcomFamiliesTree[$i],'MARR', 'SOUR')]),
array ('Identifier' => @preg_replace('/\d ASSO @(I\d*)@/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_tag ($this->_GedcomFamiliesTree[$i], 'ASSO')]),
'Relationship' => @preg_replace('/\d RELA (.*)/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_subTag ($this->_GedcomFamiliesTree[$i],'ASSO', 'RELA')])
@preg_replace('/\d DATE (.*)/US', '$1', $this->_GedcomFamiliesTree[$i][$this->_subTag ($this->_GedcomFamiliesTree[$i],'DIV', 'DATE')])
$this->GedcomFamiliesTreeObjects[] = & new Genealogy_Family($Genealogy_Family_Param);
unset ($Genealogy_Family_Param);
* Create an array of Genealogy_Object object
function _parseObjects () { // IMGC -> Parentele
for ($i = 0; $i < count($this->_GedcomObjectsTree); $i++ ) {
$Genealogy_Object_Param = array (@preg_replace('/0 @(O\d*)@ OBJE/US', '$1', $this->_GedcomObjectsTree[$i][0 ]),
@preg_replace('/\d FILE (.*)/US', '$1', $this->_GedcomObjectsTree[$i][$this->_tag ($this->_GedcomObjectsTree[$i],'FILE')])
$this->GedcomObjectsTreeObjects[] = & new Genealogy_Object($Genealogy_Object_Param);
unset ($Genealogy_Object_Param);
* @return integer subtag id or nothing
function _subTag ($tab, $mainTag, $tag) {
$i = $this->_tag ($tab, $mainTag);
for ($j= $i+1; $j < count($tab); $j++ ) {
if ($level < $tab[$j]{0 }) {
if (@preg_match('/\d '. $tag. ' (.*)/US', $tab[$j])) {
* @return integer tag id or 20 (force error)
function _tag ($tab, $tag) {
for ($i=0; $i < count($tab); $i++ ) {
if (@preg_match('/'. $tag. '/US', $tab[$i])) return $i;
* Get tag contain with CONT
* @return string tag contain
function _contTag ($tab, $mainTag) {
$i = $this->_tag ($tab, $mainTag);
$level = (integer) $tab[$i]{0 };
// first line with main tag
$str .= @preg_replace('/'. $level. ' '. $mainTag. ' (.*)/US', '$1', $tab[$i]);
// continue string with others CONT tag
if (isset ($tab[$i]) && $level < $tab[$i]{0 }) {
$str .= "\n". @preg_replace('/\d CONT (.*)/US', '$1', $tab[$i]);
} while ($i < count($tab));
* Get an array of tags contains
* example for children (CHIL)
function _arrayTag ($tab, $tag) {
for ($i=0; $i < count($tab); $i++ ) {
$arr[] = @preg_replace('/\d '. $tag. ' @(.*)@/US', '$1', $tab[$i]);
function _arrayWitnessTag ($tab) {
for ($i= $this->_tag ($tab, 'WITN'); $i < count($tab); $i++ ) {
$arr[$k]['Name'] = trim(@preg_replace('/\d NAME (.*)\/(.*)\//US', '$1 $2', $tab[$i]));
$arr[$k]['Title'] = @preg_replace('/\d TITL (.*)/US', '$1', $tab[$i]);
if (isset ($arr[$k]['Name']) && isset ($arr[$k]['Title'])) {
Documentation generated on Mon, 11 Mar 2019 14:18:35 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.
|