/// -------------------------------------------------------------------------------- /// <summary> /// Adds text to a new segment or append text to an existing segment if needed. /// </summary> /// <param name="ichBeginTR">The beginning character offset of the segment.</param> /// <param name="segmentBTsForPara">List of segments for the para.</param> /// <param name="tssAppendKey">The TSS append key.</param> /// <param name="tssAddKey">The TSS add key.</param> /// -------------------------------------------------------------------------------- private void AddOrAppendToSegIfNeeded(int ichBeginTR, List<BTSegment> segmentBTsForPara, ITsString tssAppendKey, ITsString tssAddKey) { int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR <= ichBeginTR) return; // no paragraph contents to add or append int iseg = segmentBTsForPara.Count - 1; if (iseg >= 0 && segmentBTsForPara[iseg] != null && (segmentBTsForPara[iseg].GetBackTransForWs(0) == m_tssChapterStartKey || segmentBTsForPara[iseg].GetBackTransForWs(0) == m_tssLabelTrKey || segmentBTsForPara[iseg].GetBackTransForWs(0) == m_tssVerseStartKey) && segmentBTsForPara[iseg].Text != null) { // Found a previous segment to which we need to append BTSegment bts = segmentBTsForPara[iseg]; bts.EndOffset = ichEndTR; ITsStrBldr tsb = bts.Text.GetBldr(); tsb.Append(NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.Text = tsb.GetString(); bts.SetBackTransForWs(0, tssAppendKey); } else { // Need to create a new segment BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.SetBackTransForWs(0, tssAddKey); segmentBTsForPara.Add(bts); } }
/// ----------------------------------------------------------------------------------- /// <summary> /// Read in one paragraph's worth of data. This includes both the translated data and /// the back translated data, as well as any footnotes or annotations encountered along /// the way. The footnotes and annotations are created, but the translated data and /// back translated data are left waiting for a call to StoreXmlParagraphData(). /// </summary> /// <param name="xnPara">XML node with paragraph information</param> /// <param name="fNew"><c>true</c> to start a new paragraph; <c>false</c> to continue /// adding content to an existing paragraph</param> /// <param name="sect">The section of which this paragraph is a part</param> /// <param name="annotationsForPara">List of any annotations added or modified for this /// paragraph (needed so that the begin/end object properties can be set once the para /// is actually created)</param> /// <param name="segmentBTsForPara"></param> /// <returns>true if any data was read, false otherwise</returns> /// ----------------------------------------------------------------------------------- private bool ReadXmlParagraphData(XmlNode xnPara, bool fNew, IScrSection sect, List<IScrScriptureNote> annotationsForPara, List<BTSegment> segmentBTsForPara) { if (fNew) ClearParagraphStringBuilders(); bool fData = false; // the following strings are used as markers in the rgmapwstssBT list. ITsString tssChapterStart = m_cache.MakeUserTss("chapterStart"); ITsString tssVerseStart = m_cache.MakeUserTss("verseStart"); ITsString tssChapterVerse = m_cache.MakeUserTss("chapter:verse"); ITsString tssNote = m_cache.MakeUserTss("note"); ITsString tssFigure = m_cache.MakeUserTss("figure"); Dictionary<int, ITsString> mapwstss = new Dictionary<int, ITsString>(); List<IScrScriptureNote> rgnotesForSegment = new List<IScrScriptureNote>(); bool fImportSegmentedBT = true; foreach (XmlNode node in xnPara.ChildNodes) { int ichBeginTR = NormalizedLength(m_ParaBldr.StringBuilder); mapwstss.Clear(); if (node.Name == "trGroup") { fImportSegmentedBT &= Options.UseInterlinearBackTranslation; foreach (XmlNode xn in node.ChildNodes) { string sLang = XmlUtils.GetOptionalAttributeValue(xn, "xml:lang", null); int ws; if (String.IsNullOrEmpty(sLang)) ws = xn.Name == "bt" ? m_wsAnal : m_wsVern; else ws = GetWsForLang(sLang); if (xn.Name == "tr") { ReadXmlStringElement(xn, ws, null, m_ParaBldr.StringBuilder); fData = true; } else if (xn.Name == "bt") { fImportSegmentedBT &= XmlUtils.GetOptionalBooleanAttributeValue(xn, "segmented", false); ITsStrBldr tsb = GetBackTransStringBuilder(ws); ITsStrBldr tsbNumber = GetBackTransNumberStringBuilder(ws); if (tsbNumber.Length > 0) { tsb.ReplaceTsString(tsb.Length, tsb.Length, tsbNumber.GetString()); tsbNumber.Clear(); } int cchBegin = NormalizedLength(tsb); ReadXmlStringElement(xn, ws, null, tsb); string status = XmlUtils.GetOptionalAttributeValue(xn, "status"); string statusT; if (!String.IsNullOrEmpty(status) && !m_BTStatus.TryGetValue(ws, out statusT)) m_BTStatus.Add(ws, status); fData = true; mapwstss.Add(ws, NormalizedSegment(tsb, cchBegin)); foreach (XmlNode xnChild in xn.ChildNodes) { if (xnChild.Name == "annotation") { IScrScriptureNote ann = XmlScrNote.Deserialize(xnChild, m_scr, m_styleSheet); if (ann != null) rgnotesForSegment.Add(ann); } } } else if (xn is XmlElement) { throw new Exception("OXES validation failed to detect an unexpected tag in the <trGroup>."); } } int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR > ichBeginTR || rgnotesForSegment.Count > 0) { BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); foreach (int ws in mapwstss.Keys) bts.SetBackTransForWs(ws, mapwstss[ws]); if (rgnotesForSegment.Count > 0) { bts.Annotations = rgnotesForSegment; rgnotesForSegment.Clear(); } segmentBTsForPara.Add(bts); } } else if (node.Name == "chapterStart" || node.Name == "chapterEnd") { ProcessChapterNumber(node); if (m_ParaBldr.Length > 0) fData = true; int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR > ichBeginTR) { BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.SetBackTransForWs(0, tssChapterStart); segmentBTsForPara.Add(bts); } } else if (node.Name == "verseStart" || node.Name == "verseEnd") { ProcessVerseNumber(node); if (m_ParaBldr.Length > 0) fData = true; int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR > ichBeginTR) { int iseg = segmentBTsForPara.Count - 1; if (iseg >= 0 && segmentBTsForPara[iseg] != null && segmentBTsForPara[iseg].GetBackTransForWs(0) == tssChapterStart && segmentBTsForPara[iseg].Text != null && segmentBTsForPara[iseg].Text.Length <= 3 && ichEndTR - ichBeginTR <= 9) // allows verse "100b-101a" { BTSegment bts = segmentBTsForPara[iseg]; bts.EndOffset = ichEndTR; ITsStrBldr tsb = bts.Text.GetBldr(); tsb.ReplaceTsString(tsb.Length, tsb.Length, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.Text = tsb.GetString(); bts.SetBackTransForWs(0, tssChapterVerse); } else { BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.SetBackTransForWs(0, tssVerseStart); segmentBTsForPara.Add(bts); } } } else if (node.Name == "note") { ProcessFootnote(node); int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR > ichBeginTR) { BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.SetBackTransForWs(0, tssNote); segmentBTsForPara.Add(bts); } } else if (node.Name == "annotation") { IScrScriptureNote ann = XmlScrNote.Deserialize(node, m_scr, m_styleSheet); if (ann != null) annotationsForPara.Add(ann); } else if (node.Name == "figure") { ProcessFigure(node); int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR > ichBeginTR) { BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.SetBackTransForWs(0, tssFigure); segmentBTsForPara.Add(bts); } } else if (node.Name == "p") { if (m_stackXmlContext.Count == 0) { throw new ScriptureUtilsException(SUE_ErrorCode.UnexpectedParagraph, m_sOXESFile, (m_reader != null) ? m_reader.LineNumber : 0, node.OuterXml.Substring(0, node.OuterXml.IndexOf(">") + 1), m_currentRef); } string sContext = m_stackXmlContext.Peek(); if ((sContext == ScrStyleNames.ListItem1 || sContext == ScrStyleNames.ListItem2) && sect != null) { if (fData) StoreXmlParagraphData(sect.ContentOAHvo, sContext, annotationsForPara, segmentBTsForPara); string sStyle = (sContext == ScrStyleNames.ListItem1) ? ScrStyleNames.ListItem1Additional : ScrStyleNames.ListItem2Additional; if (ReadXmlParagraphData(node, true, sect, annotationsForPara, segmentBTsForPara)) StoreXmlParagraphData(sect.ContentOAHvo, sStyle, annotationsForPara, segmentBTsForPara); fData = false; } else if (node is XmlElement) { throw new Exception("OXES validation failed to detect a <p> tag within a <p> tag."); } } else if (node is XmlElement) { throw new Exception("OXES validation failed to find a valid tag within a <p> tag."); } } if (!fImportSegmentedBT) segmentBTsForPara.Clear(); return fData; }
/// ----------------------------------------------------------------------------------- /// <summary> /// Read in one paragraph's worth of data. This includes both the translated data and /// the back translated data, as well as any footnotes or annotations encountered along /// the way. The footnotes and annotations are created, but the translated data and /// back translated data are left waiting for a call to StoreXmlParagraphData(). /// </summary> /// <param name="xnPara">XML node with paragraph information</param> /// <param name="fNew"><c>true</c> to start a new paragraph; <c>false</c> to continue /// adding content to an existing paragraph</param> /// <param name="sect">The section of which this paragraph is a part</param> /// <param name="annotationsForPara">List of any annotations added or modified for this /// paragraph (needed so that the begin/end object properties can be set once the para /// is actually created)</param> /// <param name="segmentBTsForPara"></param> /// <returns>true if any data was read, false otherwise</returns> /// ----------------------------------------------------------------------------------- private bool ReadXmlParagraphData(XmlNode xnPara, bool fNew, IScrSection sect, List<IScrScriptureNote> annotationsForPara, List<BTSegment> segmentBTsForPara) { if (fNew) ClearParagraphStringBuilders(); bool fData = false; Dictionary<int, ITsString> mapwstss = new Dictionary<int, ITsString>(); List<IScrScriptureNote> rgnotesForSegment = new List<IScrScriptureNote>(); bool fImportSegmentedBT = true; foreach (XmlNode node in xnPara.ChildNodes) { int ichBeginTR = NormalizedLength(m_ParaBldr.StringBuilder); mapwstss.Clear(); if (node.Name == "trGroup") { foreach (XmlNode xn in node.ChildNodes) { string sLang = XmlUtils.GetOptionalAttributeValue(xn, "xml:lang", null); int ws; if (String.IsNullOrEmpty(sLang)) ws = xn.Name == "bt" ? m_wsAnal : m_wsVern; else ws = GetWsForLang(sLang); if (xn.Name == "tr") { ReadXmlStringElement(xn, ws, null, m_ParaBldr.StringBuilder); fData = true; } else if (xn.Name == "bt") { fImportSegmentedBT &= XmlUtils.GetOptionalBooleanAttributeValue(xn, "segmented", false); ITsStrBldr tsb = GetBackTransStringBuilder(ws); ITsStrBldr tsbNumber = GetBackTransNumberStringBuilder(ws); if (tsbNumber.Length > 0) { tsb.ReplaceTsString(tsb.Length, tsb.Length, tsbNumber.GetString()); tsbNumber.Clear(); } int cchBegin = NormalizedLength(tsb); ReadXmlStringElement(xn, ws, null, tsb); string status = XmlUtils.GetOptionalAttributeValue(xn, "status"); string statusT; if (!String.IsNullOrEmpty(status) && !m_BTStatus.TryGetValue(ws, out statusT)) m_BTStatus.Add(ws, status); fData = true; mapwstss.Add(ws, NormalizedSegment(tsb, cchBegin)); foreach (XmlNode xnChild in xn.ChildNodes) { if (xnChild.Name == "annotation") { IScrScriptureNote ann = XmlScrNote.Deserialize(xnChild, m_scr, m_styleSheet); if (ann != null) rgnotesForSegment.Add(ann); } } } else if (xn is XmlElement) { throw new Exception("OXES validation failed to detect an unexpected tag in the <trGroup>."); } } int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR > ichBeginTR || rgnotesForSegment.Count > 0) { BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); foreach (int ws in mapwstss.Keys) bts.SetBackTransForWs(ws, mapwstss[ws]); if (rgnotesForSegment.Count > 0) { bts.Annotations = rgnotesForSegment; rgnotesForSegment.Clear(); } segmentBTsForPara.Add(bts); } } else if (node.Name == "chapterStart" || node.Name == "chapterEnd") { ProcessChapterNumber(node); if (m_ParaBldr.Length > 0) fData = true; AddOrAppendToSegIfNeeded(ichBeginTR, segmentBTsForPara, m_tssChapterStartKey, m_tssChapterStartKey); } else if (node.Name == "verseStart" || node.Name == "verseEnd") { ProcessVerseNumber(node); if (m_ParaBldr.Length > 0) fData = true; AddOrAppendToSegIfNeeded(ichBeginTR, segmentBTsForPara, m_tssVerseStartKey, m_tssVerseStartKey); } else if (node.Name == "note") { if (XmlUtils.GetOptionalAttributeValue(node, "Id") != null) { ProcessFootnote(node); int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR > ichBeginTR) { BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.SetBackTransForWs(0, m_tssNoteKey); segmentBTsForPara.Add(bts); } } else { Debug.Fail("Need to handle note references."); //Debug.Assert(XmlUtils.GetOptionalAttributeValue(node, "Ref") != null, // "Did not find expected reference to a footnote"); //ProcessFootnoteRef(node); } } else if (node.Name == "annotation") { IScrScriptureNote ann = XmlScrNote.Deserialize(node, m_scr, m_styleSheet); if (ann != null) annotationsForPara.Add(ann); } else if (node.Name == "figure") { ProcessFigure(node); int ichEndTR = NormalizedLength(m_ParaBldr.StringBuilder); if (ichEndTR > ichBeginTR) { BTSegment bts = new BTSegment(ichBeginTR, ichEndTR, NormalizedSegment(m_ParaBldr.StringBuilder, ichBeginTR)); bts.SetBackTransForWs(0, m_tssFigureKey); segmentBTsForPara.Add(bts); } } else if (node.Name == "p") { if (m_stackXmlContext.Count == 0) throw new Exception("OXES validation failed to detect an unexpected paragraph element"); string sContext = m_stackXmlContext.Peek(); if ((sContext == ScrStyleNames.ListItem1 || sContext == ScrStyleNames.ListItem2) && sect != null) { if (fData) StoreXmlParagraphData(sect.ContentOA, sContext, annotationsForPara, segmentBTsForPara); string sStyle = (sContext == ScrStyleNames.ListItem1) ? ScrStyleNames.ListItem1Additional : ScrStyleNames.ListItem2Additional; if (ReadXmlParagraphData(node, true, sect, annotationsForPara, segmentBTsForPara)) StoreXmlParagraphData(sect.ContentOA, sStyle, annotationsForPara, segmentBTsForPara); fData = false; } else if (node is XmlElement) { throw new Exception("OXES validation failed to detect a <p> tag within a <p> tag."); } } else if (node.Name == "labelTr") { ReadXmlStringElement(node, m_wsVern, null, m_ParaBldr.StringBuilder); fData = true; AddOrAppendToSegIfNeeded(ichBeginTR, segmentBTsForPara, m_tssLabelTrKey, m_tssLabelTrKey); } else if (node is XmlElement) { throw new Exception("OXES validation failed to find a valid tag within a <p> tag."); } } if (!fImportSegmentedBT) segmentBTsForPara.Clear(); return fData; }