<package> <job id="G2X"> <?job debug="true"?> <runtime><description><![CDATA[GEDCOM one-to-one to XML: view source for usage and options ...]]></description></runtime> <script language="JScript" src="ANSELentify.js"> // ----------------------------------------------------------------- //~ //~ GEDCOM one-to-one to XML for "Windows Script Host" (WSH) //~ USAGE: cscript //nologo ged1212xml.wsf [/name:value [...]] [<stdin.ged] [>stdout.xml] [2>stderr.log] //~ NOTES: double slashes for cscript-arguments, e.g. //nologo, single slashes for wsf-arguments //~ NCName represents XML "non-colonized" Names (no-colon constraint) //~ OPTIONS: //~ FILES //~ /ged:<file.ged> //~ GEDCOM input-filename, default=STDIN //~ /xml:<file.xml> //~ XML output-filename, default=STDOUT //~ /log:<file.log> //~ Logging output-filename, default=STDERR //~ GED-INPUT-ENCODING-MODE //~ /ans:true //~ start "ANSEL to Entity"-mode before 1st occurence of +n CHAR ANSEL //~ XML-OUTPUT //~ /nspfx:<ncname> //~ xml namespace prefix, requires setting of /uri:<URI> too, default=none //~ /nsuri:<URI> //~ xml namespace URI for xmlns[:nsPFX]="...", default=none //~ /enc:"iso-8859-1"|<encoding> //~ replace xml declaration's default <?xml ... encoding="iso-8859-1" ?> //~ /sty:<file.css|file.xsl> //~ insert processing-instruction <?xml-stylesheet ... href="..."?>, default=none //~ /root:"GED"|<ncname> //~ replace root-element's default tag-name "GED" //~ /id:"ID"|"xml:id"|<ncname> //~ replace attribute-name's default "ID" for GEDCOM's @<XREF>@s //~ /ref:"REF"|<ncname> //~ replace attribute-name's default "REF" for GEDCOM's @<XREF>@s //~ /dtd:""|<file.dtd> //~ insert doctype-definition <!DOCTYPE ... SYSTEM "...">, default=none //~ /xsd:""|<file.xsd> //~ insert root's xsi:XMLSchema-instance-location-definition, default=none //~ /idpfx=""|"id."|"ged-"|<ncname> //~ ID-prefix for valid xmlID/REF-values (NCNames), default=none //~ ID-prefix == string-additive, don't confuse it with namespace-prefixes! //~ /esc:""|"ESC"|<ncname> //~ given name ("ESC" preferred, default=none=noop) //~ moves @#<DATE_CALENDAR_ESCAPE>@s into attributes //~ /sur:"SURN"|"S"|<ncname>|<!ncname> //~ alter node-name ("S" preferred, default="SURN") for slashed surname-part //~ to avoid double SURN-subnodes in an extended NAME-node/structure //~ a non-ncname char/string prevents slash-replacement at all //~ /pi:""|"attr"|"func"|"void"|"nopi" //~ predefined attribute- or function-style for processing-instructions //~ default="void" ~ empty for user-defined styles, otherwise plain style //~ a non-defined value (like "nopi") prevents PI-generation at all //~ /pincn:""|<ncname> //~ PI-ncname for processing-instruction-targetnames, default=none //~ /datepi:"DATE"|<ncname>|<!ncname> //~ processing-instruction-targetname, default="DATE" becomes <?DATE ...?> //~ date-format converted (if possible) to YYYY-MM-DD according to ISO 8601 //~ a non-ncname char/string prevents DATE PI-generation //~ /uuidpi:"_UID"|"GUID"|"UUID"|"XUID"|"UURN"|"XURN"|<ncname>|<!ncname> //~ processing-instruction-targetname, default="UUID" becomes <?UUID ...?> //~ Universally Unique IDentifiers v4 (pseudo-random) according to RFC 4122 //~ a standard-name is default-format for uuidsty-option //~ a non-ncname char/string prevents UUID PI-generation //~ /_uidpi:"_UID"|"GUID"|"UUID"|"XUID"|"UURN"|"XURN"|<ncname>|<!ncname> //~ processing-instruction-targetname, default="_UID" becomes <?_UID_n ...?> //~ checks _UID-tag, default according to PAF-style UUID+Checksum (n=0|1|X) //~ a standard-name is default-format for _uidsty-option //~ a non-ncname char/string prevents _UID PI-generation //~ /uuidsty:<uuidPI-standard-targetname-format>|"UUID"|<targetformat> //~ /_uidsty:<_uidPI-standard-targetname-format>|"_UID"|<targetformat> //~ default-format-1 : targetname of PI if predef'd standard-format //~ default-format-2 : formatname "[_U]UID" if PI-name is non-standard //~ default-format-3 : else-clause-format if user-def'd is non-standard //~ "_UID" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXCCCC (_uidsty-default) //~ PAF-GEDCOM-_UID 16+2 bytes, 36 chars uppercase hexdigit with checksum //~ "UUID" xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (uuidsty-default) //~ RFC-4122-UUIDv4 16 bytes, 32+4 chars lowercase hexdigit hyphen-grouped //~ "GUID" {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} //~ embraced {UUIDv4} 16 bytes, 32+6 chars uppercase hexdigit hyphen-grouped //~ "XUID" {XxxxXXXx-XXxX-xXXx-xxXX-XxXxxXXXxXxX}cccc //~ extended mixedcase and -style {GUIDv4}, 4-hexdigit checksum appended //~ "UURN" urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx //~ prefixed lowercase "urn:uuid:UUIDv4" (RFC-4122, UUID as URN) //~ "XURN" urn:uuid:XXXxxXxX-xxXx-XxXX-XXXX-xXXXXXxXxxxX+cccc //~ extended mixedcase "urn:uuid:UUIDv4+checksum" (RFCs 2141+3986+4122) //~ else: xXxXXxXX-xXXx-XXxx-XxxX-xxxxXXxxXxxX cccc //~ combined mixedcase UUIDv4 with 4-hexdigit checksum (set apart) //~ /seed:noop //~ built-in random() not seedable in ECMAScript //~ // ----------------------------------------------------------------- //~ //~ Copyright (c) 2008 ff. Stefan Unterstein <http://www.unterstein.net/ged1212xml> //~ //~ By operation of rights, permission is hereby granted to copy, distribute and/or //~ modify this program under the terms of the GNU General Public License Version 3 //~ or any later version published by the Free Software Foundation. See the current //~ License at <http://www.gnu.org/licenses/gpl.html> for more details. //~ //~ Such free(d) "copylefted" software is distributed //~ WITHOUT ANY WARRANTY OF OR ABOUT ANYTHING but the "copyleft" itself. //~ // ----------------------------------------------------------------- </script> <script language="JScript"> // ----------------------------------------------------------------- //~ UUID-code derived and varied from //~ https://github.com/broofa/node-uuid //~ http://www.broofa.com/Tools/Math.uuid.js //~ http://www.broofa.com/2008/09/javascript-uuid-function/ //~ http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript //~ UUID-spec http://tools.ietf.org/html/rfc4122.html //~ diff.spec.: output of randomly mixed-case letters // ----------------------------------------------------------------- var xcharX = "89AB89ab01234567cdef01234567CDEF".split(""); // 31 random() per UUID, miXed case - var uuid4X = function() { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function($0){ return xcharX[0|Math.random()*{"x":32,"y":8}[$0]]; }); } - var uuid4x = function() { return ("xxxxxxxx-xxxx-4xxx-"+xcharX[0|Math.random()*8]+"xxx-xxxxxxxxxxxx").replace(/x/g, function(){ return xcharX[0|Math.random()*32]; }); } - var uuid4v = function() { // 5 random() assignments per UUID, miXed case var r, c=xcharX; return [ c[(r=Math.random()*0x100000000)&0x1f], // 5 bits for val./pos.0-31 c[(r>>> 5)&0x1f], c[(r>>>10)&0x1f], c[(r>>>15)&0x1f], c[(r>>>20)&0x1f], c[(r>>>25)&0x1f], c[(r=Math.random()*0x100000000)&0x1f], c[(r>>> 5)&0x1f], "-", c[(r>>>10)&0x1f], c[(r>>>15)&0x1f], c[(r>>>20)&0x1f], c[(r>>>25)&0x1f], "-", "4", c[(r=Math.random()*0x100000000)&0x1f], c[(r>>> 5)&0x1f], c[(r>>>10)&0x1f], "-", c[(r>>>15)&0x07], // use 3 of 5 bits for val./pos.0-7 of [8,9,A,B,8,9,a,b,... c[(r>>>17)&0x1f], // re-use 1 of prev.3 bits (6*5+2=32 bits available) c[(r>>>22)&0x1f], c[(r>>>27)&0x1f], "-", c[(r=Math.random()*0x100000000)&0x1f], c[(r>>> 5)&0x1f], c[(r>>>10)&0x1f], c[(r>>>15)&0x1f], c[(r>>>20)&0x1f], c[(r>>>25)&0x1f], c[(r=Math.random()*0x100000000)&0x1f], c[(r>>> 5)&0x1f], c[(r>>>10)&0x1f], c[(r>>>15)&0x1f], c[(r>>>20)&0x1f], c[(r>>>25)&0x1f] ].join(""); } // ----------------------------------------------------------------- //~ http://wiki-de.genealogy.net/UID-Tag //~ http://www.tamurajones.net/The_UIDTag.xhtml //~ https://devnet.familysearch.org/docs/gedcom/GEDCOMUniqueIdentifiers.pdf // ----------------------------------------------------------------- - var uuid4matter = function(UUID,fmt) { var BytesSum1 = 0, ChecksB17 = 0; var BytesSum2 = 0, ChecksB18 = 0; var JointUUID = UUID.split("-").join("").substr(0,32); for (var n=0; n<16; n++) - { BytesSum1 += parseInt(JointUUID.substr(n*2,2),16); BytesSum2 += BytesSum1; } ChecksB17 = BytesSum1 % 256; ChecksB18 = BytesSum2 % 256; var ChecksHex = (ChecksB17<16?"0":"") + ChecksB17.toString(16) + (ChecksB18<16?"0":"") + ChecksB18.toString(16); var CanonUUID = JointUUID.substr(0,8)+"-"+JointUUID.substr(8,4)+"-"+JointUUID.substr(12,4)+"-"+JointUUID.substr(16,4)+"-"+JointUUID.substr(20,12); switch (fmt||"") - { case "XUID" : return "{" + CanonUUID + "}" + ChecksHex; case "XURN" : return "urn:uuid:" + CanonUUID + "+" + ChecksHex; case "UURN" : return "urn:uuid:" + CanonUUID.toLowerCase(); case "_UID" : return (JointUUID + ChecksHex).toUpperCase(); case "GUID" : return "{" + CanonUUID.toUpperCase() + "}"; case "UUID" : return CanonUUID.toLowerCase(); default : return CanonUUID + " " + ChecksHex; } } function gedPIUUID(target) { return xmlPI(target,uuid4matter(uuid4v(),uuidSTY)); } var RExurn = /(?:urn:uuid:)?/i; var RExuid = /(\{?[0-9a-f]{2}(?:-?[0-9a-f]{2}){14}-?[0-9a-f]{2}\}?(?:[- +]?[0-9a-f]{2}-?[0-9a-f]{2})?)/i; - function gedPI_UID(arg_UID) { var gvn_UID = RExuid.test(arg_UID) ? (RegExp.$1).replace(/[-{ }+]/g,"") : "" ; if (gvn_UID) - { //~ var val_UID = (gvn_UID.length>=32) ? gvn_UID.substr(0,32) : "" ; //~ var chk_UID = (gvn_UID.length==36) ? gvn_UID.substr(32,4) : "" ; var cmp_UID = uuid4matter(gvn_UID,_uidSTY); if (arg_UID==cmp_UID) - { return xmlPI(_uidPI+"_1",cmp_UID); // // true _uidSTY-format and value, comp'd and given ID+checksum are identical // if _UID-style (default), value and format are likely to be accepted by PAF-compatibles // } else { return xmlPI(_uidPI+"_X",cmp_UID); // // true UUID 128-bit value, but false format or checksum, or surplus characters // value now preserved and transformed into _uidSTY-format, accordingly plus new checksum // if _UID-style and not eXchanged, this and next are likely to be rejected by PAF-compatibles // } } else { return xmlPI(_uidPI+"_0",uuid4matter(uuid4v(),_uidSTY)); // // false, no (valid) UUID or 128-bit-value available, new UUID in _uidSTY-format generated // } } // ----------------------------------------------------------------- // ----------------------------------------------------------------- </script> <script language="JScript"> // ----------------------------------------------------------------- // parse args, echo usage // ----------------------------------------------------------------- var oArgs = WScript.Arguments; var nArgs = WScript.Arguments.Named; // /name:value var uArgs = WScript.Arguments.Unnamed; var Usage = "Usage: cscript \/\/NoLogo [\/\/job:G2X] [absPath]"+WScript.ScriptName+" [\/ged:|\/xml:|\/log:[\"]file.ged|.xml|.log[\"]] [< stdin.ged] [> stdout.xml] [2> stderr.log] \n... view source for more options"; if (uArgs.length || nArgs.length>24 || oArgs.length!=nArgs.length) { WScript.Echo(Usage); WScript.Quit(1); } var aName = { "ged":"", "xml":"", "log":"", "nspfx":"", "nsuri":"", "enc":"", "sty":"", "root":"", "id":"", "ref":"", "dtd":"", "xsd":"", "idpfx":"", "pi":"", "pincn":"", "esc":"", "sur":"", "ans":"", "datepi":"", "uuidpi":"", "_uidpi":"", "_uidsty":"", "uuidsty":"", "seed":"" }; if (nArgs.length) // case-insensitive for NAME in /NAME:value pairs if lowercase name-key in aName-Object - { - for (var idx=0; idx<oArgs.length; idx++) { if (/^\/(\w+?):/.test(oArgs(idx)) && nArgs.Exists(RegExp.$1) && ((RegExp.$1).toLowerCase() in aName)) aName[(RegExp.$1).toLowerCase()]=nArgs.Item(RegExp.$1); } } - /* if (nArgs.length) // name-key case-sensitive for NAME in /NAME:value pairs { for (var idx in aName) { if (nArgs.Exists(idx)) aName[idx]=nArgs.Item(idx); } } */ var FSO = new ActiveXObject("Scripting.FileSystemObject"); - var aFile = { "ged" : ( (aName.ged) ? FSO.OpenTextFile (aName.ged, 1) : WScript.StdIn ), "xml" : ( (aName.xml) ? FSO.CreateTextFile (aName.xml, true) : WScript.StdOut ), "log" : ( (aName.log) ? FSO.CreateTextFile (aName.log, true) : WScript.StdErr ) } aName.ged = aName.ged||"STDIN"; aName.xml = aName.xml||"STDOUT"; aName.log = aName.log||"STDERR"; var REncname = /^[a-z_A-Z][-a-z_A-Z.0-9]*$/; var REncnORnone = /^$|^[a-z_A-Z][-a-z_A-Z.0-9]*$/; - if (aName.nspfx && !aName.nsuri) { WScript.StdErr.WriteLine("Error: xmlNamespace \/nspfx:Prefix w\/o \/nsuri:URI\n"+Usage); WScript.Quit(1); } - if (!REncnORnone.test(aName.nspfx) || !REncnORnone.test(aName.idpfx) || !REncnORnone.test(aName.pincn)) { WScript.StdErr.WriteLine("Error: (nspfx|idpfx|pincn) require a valid NCName\n"+Usage); WScript.Quit(1); } // ----------------------------------------------------------------- // ----------------------------------------------------------------- var $AP = Array.prototype; // var args = [].slice.call(arguments,0); String.prototype.attr = function(NMTOKEN) { return (this.valueOf())?" "+NMTOKEN+"=\""+this+"\"":""; } String.prototype.func = function(NMTOKEN) { return (this.valueOf())?" "+NMTOKEN+"(\""+this+"\");":""; } String.prototype["void"]= function(NMTOKEN) { return (this.valueOf())?" "+this:""; } String.prototype.mark = function(NMTOKEN) { return (this.valueOf())?"<"+NMTOKEN+">"+this+"<\/"+NMTOKEN+">":"<"+NMTOKEN+" \/>"; } String.prototype.markup = function(/*NMTOKENS*/) { return "<"+$AP.join.call(arguments,"><")+">"+this+"<\/"+$AP.slice.call(arguments,0).reverse().join("><\/")+">"; } String.prototype.markUP = function(/*NMTOKENS*/) { return ["<",$AP.join.call(arguments,"><"),">",this,"<\/",$AP.slice.call(arguments,0).reverse().join("><\/").replace(/\s+[^>]*/gi,""),">"].join(""); } String.prototype.entify = function() { return (this.valueOf())?this.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"):this; } Boolean.prototype.attr = String.prototype.attr; Boolean.prototype.func = String.prototype.func; Boolean.prototype.mark = String.prototype.mark; var Report = ['@@report']; - var updateReport = function(s) { if (s instanceof Array) Report=Report.concat(s); else if ((typeof(s)=='string')||(s instanceof String)) Report[Report.length]=s; } - var returnReport = function() { return Report.join('\r\n')+'\r\n@@\r\n'; } // ----------------------------------------------------------------- // ----------------------------------------------------------------- var gedFile = aFile.ged; var gedFileName = aName.ged; var xmlFile = aFile.xml; var xmlFileName = aName.xml; var logFile = aFile.log; var logFileName = aName.log; var xmlEnc = aName.enc||"iso-8859-1"; var xmlStyle = (/\.(css|xsl)$/i.test(aName.sty)) ? "\n<?xml-stylesheet type=\"text\/"+(RegExp.$1).toLowerCase()+"\" href=\""+aName.sty+"\"?>" : "" ; var xmlRoot = aName.root||"GED"; var xmlID = aName.id||"ID"; var xmlIDREF = aName.ref||"REF"; var xmlnsATTR = (aName.nsuri) ? ((aName.nspfx) ? " xmlns:"+aName.nspfx+"=\""+aName.nsuri+"\"" : " xmlns=\""+aName.nsuri+"\"") : "" ; var xmlnsPFX = (aName.nspfx) ? aName.nspfx+":" : "" ; var xmlDTD = (aName.dtd) ? "\n<!DOCTYPE "+xmlnsPFX+xmlRoot+" SYSTEM \""+aName.dtd+"\">" : "" ; var xsiXSD = (aName.xsd) ? " xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\""+((aName.uri) ? " xsi:schemaLocation=\""+aName.uri+" " : " xsi:noNamespaceSchemaLocation=\"")+aName.xsd+"\"" : "" ; var encANSEL = Boolean(aName.ans)||false; if (encANSEL) { updateReport("GEDCOM input-encoding preset to ANSEL"); } var surNAME = (aName.sur!="") ? ((/^[a-zA-Z_]\w*$/.test(aName.sur)) ? aName.sur : "") : "SURN" ; var escDATE = aName.esc||""; var idPFX = aName.idpfx||""; var piNCN = aName.pincn||""; var piSTY = (/^(?:attr|func|void)$/.test(aName.pi)) ? aName.pi : (aName.pi=="") ? "void" : "" ; var datePI = (aName.datepi!="") ? ((REncname.test(aName.datepi)) ? aName.datepi : "") : "DATE" ; var uuidPI = (aName.uuidpi!="") ? ((REncname.test(aName.uuidpi)) ? aName.uuidpi : "") : "UUID" ; var _uidPI = (aName._uidpi!="") ? ((REncname.test(aName._uidpi)) ? aName._uidpi : "") : "_UID" ; var _uidSTY = (aName._uidsty) ? aName._uidsty : ((/^(?:[_GUX]UID|[UX]URN)$/.test(_uidPI)) ? _uidPI : "_UID") ; var uuidSTY = (aName.uuidsty) ? aName.uuidsty : ((/^(?:[_GUX]UID|[UX]URN)$/.test(uuidPI)) ? uuidPI : "UUID") ; var piSET = { "attr":{ "ncn":piNCN||xmlRoot }, "func":{ "ncn":piNCN||xmlRoot }, "void":{ "ncn":piNCN||"" } } - var GEDCOM = function(LineStr,LineNum) { this.Line = LineStr; this.LNum = LineNum; this.Valid = /\s*([0-9][0-9]?)\s+([a-zA-Z0-9_@]\S*)(?:$|\s+)(.*)/.test(this.Line); this.Level = (isNaN(RegExp.$1)) ? 0 : parseInt(RegExp.$1,10); this.Token = RegExp.$2; this.Value = (RegExp.$3) ? (RegExp.$3).entify().replace(/@@/g,"@") : false ; this.Value = (this.Value && encANSEL) ? ANSELentify(this.Value) : this.Value ; this.Id = (/^@([a-zA-Z_0-9]\S*)@$/.test(this.Token)) ? idPFX+RegExp.$1 : false ; this.IdRef = (/^@([a-zA-Z_0-9]\S*)@$/.test(this.Value)) ? (this.Value=false,idPFX+RegExp.$1) : false ; this.PI = (this.Level==0 && this.Id && piSTY && uuidPI) ? gedPIUUID(uuidPI) : "" ; return this; } var gedPrev = new GEDCOM("0 NULL", 0); gedPrev.Level = -1; gedPrev.Token = ""; gedPrev.Value = false; gedPrev.Id = false; gedPrev.IdRef = false; gedPrev.PI = ""; var tagStack = []; var tabDepth = [""]; for (var i=1; i<99; i++) tabDepth[i]=tabDepth[i-1]+" "; // var tabDepth = ["","\t","\t\t","\t\t\t","\t\t\t\t","\t\t\t\t\t","\t\t\t\t\t\t","\t\t\t\t\t\t\t","\t\t\t\t\t\t\t\t","\t\t\t\t\t\t\t\t\t"]; - function xmlClosings(gedLevel,gedPrev) { if (gedLevel> gedPrev.Level) { xmlFile.WriteLine((gedPrev.Value)?"":">"); return; } if (gedLevel==gedPrev.Level) { xmlFile.WriteLine((gedPrev.Value)?tagStack[gedPrev.Level]:"/>"+gedPrev.PI); return; } - if (gedLevel <gedPrev.Level) { xmlFile.WriteLine((gedPrev.Value)?tagStack[gedPrev.Level]:"/>"+gedPrev.PI); - for (var lvl=gedPrev.Level-1; lvl>=gedLevel; lvl--) { xmlFile.WriteLine(tabDepth[lvl]+tagStack[lvl]); } } } function xmlPI(target, value) - { return "<?" + (piSET[piSTY].ncn||target) + value[piSTY](target) + "?>"; } var mm = { "JAN":"-01-", "FEB":"-02-", "MAR":"-03-", "APR":"-04-", "MAY":"-05-", "JUN":"-06-", "JUL":"-07-", "AUG":"-08-", "SEP":"-09-", "OCT":"-10-", "NOV":"-11-", "DEC":"-12-" }; - function gedPIDATE(DATE) { // ISO: YYYY-MM-DD - if (/^([0-3]?[0-9])\s+(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\s+([0-9]?[0-9]?[0-9]?[0-9])$/.test(DATE)) { return xmlPI(datePI, [["0000","000","00","0",""][(RegExp.$3).length], RegExp.$3, mm[RegExp.$2], ["00","0",""][(RegExp.$1).length], RegExp.$1].join("")); } - if (/^(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\s+([0-9]?[0-9]?[0-9]?[0-9])$/.test(DATE)) { return xmlPI(datePI, [["0000","000","00","0",""][(RegExp.$2).length], RegExp.$2, mm[RegExp.$1], "00"].join("")); } - if (/^([0-9]?[0-9]?[0-9]?[0-9])$/.test(DATE)) { return xmlPI(datePI, [["0000","000","00","0",""][(RegExp.$1).length], RegExp.$1, "-00-00"].join("")); } return ""; } // ----------------------------------------------------------------- // ----------------------------------------------------------------- xmlFile.WriteLine("<?xml version=\"1.0\" encoding=\""+xmlEnc+"\"?>"+xmlStyle); xmlFile.WriteLine("<!-- ================================================= -->"); xmlFile.WriteLine("<!-- GEDCOM one-to-one to XML by ged1212xml.wsf (StUs) -->"); xmlFile.WriteLine("<!-- script source at http:\/\/unterstein.net\/ged1212xml -->"); xmlFile.WriteLine("<!-- ================================================= -->"+xmlDTD); xmlFile.Write ("<"+xmlnsPFX+xmlRoot+xmlnsATTR+xsiXSD); gedRead: while (!gedFile.AtEndOfStream) - { var ged$0 = gedFile.ReadLine(); var gedNR = gedFile.Line-1; - if (/^\s*$/.test(ged$0)) { updateReport("empty input-line in "+gedFileName+":"+gedNR+" skipped"); continue gedRead; } var gedThis = new GEDCOM(ged$0,gedNR); - if (gedThis.Valid) { xmlClosings(gedThis.Level,gedPrev); } else { updateReport("invalid input-line in "+gedFileName+":"+gedNR+" skipped"); updateReport("invalid input-line is "+ged$0); continue gedRead; } - if (gedThis.Level>gedPrev.Level+1) { updateReport("invalid level-increment (>1) in "+gedFileName+":"+gedNR+" detected"); } - if (gedThis.Token=="CHAR") { encANSEL = (gedThis.Value.toUpperCase()=="ANSEL") ? true : false ; updateReport("input-encoding "+gedThis.Value+" in "+gedFileName+":"+gedNR+" detected"); } if (gedThis.Level==0) xmlFile.WriteLine(); switch (gedThis.Token) - { // ----------------------------------------------------------------- // if token ~ id, value ~ token [+value(s)?] // ----------------------------------------------------------------- case ("@"+String(gedThis.Id).substr(idPFX.length)+"@") : - if (/([a-zA-Z_0-9]+)\s+(\S.*)/.test(gedThis.Value)) { xmlFile.Write(tabDepth[gedThis.Level]+"<"+xmlnsPFX+RegExp.$1+gedThis.Id.attr(xmlID)+">"+RegExp.$2); tagStack[gedThis.Level]="<\/"+xmlnsPFX+RegExp.$1+">"+gedThis.PI; } else { xmlFile.Write(tabDepth[gedThis.Level]+"<"+xmlnsPFX+gedThis.Value+gedThis.Id.attr(xmlID)); tagStack[gedThis.Level]="<\/"+xmlnsPFX+gedThis.Value+">"+gedThis.PI; gedThis.Value=""; } break; // ----------------------------------------------------------------- // enclosing AT-SHARPs mark DATE @#DTOKEN@ date calendar escape; cf. http://homepages.rootsweb.ancestry.com/~pmcbride/gedcom/55gcch2.htm#DATE_CALENDAR_ESCAPE // ----------------------------------------------------------------- case "DATE" : - if (!!escDATE && (/@#(D(?:GREGORIAN|JULIAN|HEBREW|FRENCH R|ROMAN|UNKNOWN))@\s+/.test(gedThis.Value))) { xmlFile.Write(tabDepth[gedThis.Level]+"<"+xmlnsPFX+gedThis.Token+(RegExp.$1).attr(escDATE)+">"+RegExp.rightContext); gedThis.PI=(piSTY && datePI) ? gedPIDATE((RegExp.rightContext).toUpperCase()) : "" ; } else { xmlFile.Write(tabDepth[gedThis.Level]+"<"+xmlnsPFX+gedThis.Token+((gedThis.Value)?">"+gedThis.Value:"")); gedThis.PI=(gedThis.Value && piSTY && datePI) ? gedPIDATE(gedThis.Value.toUpperCase()) : "" ; } tagStack[gedThis.Level]="<\/"+xmlnsPFX+gedThis.Token+">"+gedThis.PI; break; // ----------------------------------------------------------------- // _UID-check; cf. http://www.tamurajones.net/The_UIDTag.xhtml http://wiki-de.genealogy.net/UID-Tag // ----------------------------------------------------------------- case "_UID" : xmlFile.Write(tabDepth[gedThis.Level]+"<"+xmlnsPFX+gedThis.Token+((gedThis.Value)?">"+gedThis.Value:"")); gedThis.PI=(gedThis.Value && piSTY && _uidPI) ? gedPI_UID(gedThis.Value) : "" ; tagStack[gedThis.Level]="<\/"+xmlnsPFX+gedThis.Token+">"+gedThis.PI; break; // ----------------------------------------------------------------- // enclosing slashes mark /SURN/ surname; check for non-empty value b4! // ----------------------------------------------------------------- case "NAME" : if (!!surNAME && gedThis.Value) gedThis.Value = gedThis.Value.replace(/\/([^\/]+)\//,"<"+xmlnsPFX+surNAME+">$1<\/"+xmlnsPFX+surNAME+">").replace(/\/\//g,"<"+xmlnsPFX+surNAME+"\/>"); // ----------------------------------------------------------------- // // ----------------------------------------------------------------- default : xmlFile.Write(tabDepth[gedThis.Level]+"<"+xmlnsPFX+gedThis.Token+gedThis.IdRef.attr(xmlIDREF)+((gedThis.Value)?">"+gedThis.Value:"")); tagStack[gedThis.Level]="<\/"+xmlnsPFX+gedThis.Token+">"+gedThis.PI; break; } gedPrev = gedThis; // hold'em } xmlClosings(0,gedPrev); xmlFile.Write("\n<\/"+xmlnsPFX+xmlRoot+">"); // ----------------------------------------------------------------- // Report + Close + Quit // ----------------------------------------------------------------- gedFile.Close(); xmlFile.Close(); logFile.WriteLine ( returnReport() ); logFile.Close(); WScript.Quit(0); // ----------------------------------------------------------------- </script> </job> </package>