protected override void LoadFromReader(Stream fileStream, StreamReader reader, string streamCharset = null) { fTree.State = GDMTreeState.osLoading; try { ProgressEventHandler progressHandler = fTree.OnProgress; long fileSize = fileStream.Length; int progress = 0; var invariantText = GEDCOMUtils.InvariantTextInfo; var strTok = new GEDCOMParser(false); GDMTag curRecord = null; GDMTag curTag = null; var stack = new Stack <StackTuple>(9); XmlReaderSettings settings = new XmlReaderSettings(); settings.DtdProcessing = DtdProcessing.Ignore; int tagLevel = -1; string xrefPtr, tagName = null, tagValue = null, xrefId; int tagId = 0; // Unknown bool tagOpened = false; using (XmlReader xr = XmlReader.Create(reader, settings)) { while (xr.Read()) { if (xr.NodeType == XmlNodeType.Element) { if (tagOpened) { curTag = GEDCOMProvider.ProcessTag(stack, tagLevel, tagId, tagValue); tagOpened = false; } tagName = invariantText.ToUpper(xr.Name); // the name of the current element tagId = GEDCOMTagsTable.Lookup(tagName); tagLevel = xr.Depth - 1; // GEDML only has 2 attributes - REF and ID. xrefPtr = xr.GetAttribute("REF"); xrefId = xr.GetAttribute("ID"); tagValue = string.Empty; if (tagLevel == 0) { StackTuple stackTuple = GEDCOMProvider.AddTreeTag(fTree, tagLevel, tagId, string.Empty); if (stackTuple != null) { stack.Clear(); stack.Push(stackTuple); curRecord = stackTuple.Tag; if (!string.IsNullOrEmpty(xrefId)) { ((GDMRecord)curRecord).XRef = xrefId; } } } else if (tagLevel > 0) { if (!string.IsNullOrEmpty(xrefPtr)) { // since the default method of the GEDCOM provider is used, // a standard character `@` is expected curTag = GEDCOMProvider.ProcessTag(stack, tagLevel, tagId, "@" + xrefPtr + "@"); } else { tagOpened = true; } } } else if (xr.NodeType == XmlNodeType.Text) { tagValue = xr.Value; if (tagLevel > 0 && curRecord != null) { curTag = GEDCOMProvider.ProcessTag(stack, tagLevel, tagId, tagValue); } } if (progressHandler != null) { int newProgress = (int)Math.Min(100, (fileStream.Position * 100.0f) / fileSize); if (progress != newProgress) { progress = newProgress; progressHandler(fTree, progress); } } } } stack.Clear(); } finally { fTree.State = GDMTreeState.osReady; } }