protected bool ScanUsxDir(string usxDir) { bool result = true; try { DirectoryInfo dir = new DirectoryInfo(usxDir); foreach (FileInfo f in dir.GetFiles()) { if (f.Extension.ToLower().CompareTo(".usx") == 0) { ReadUsx(f.FullName); } } foreach (DirectoryInfo di in dir.GetDirectories()) { string fullName = Path.Combine(usxDir, di.Name); if (Directory.Exists(fullName)) { result &= ScanUsxDir(fullName); } } } catch (Exception ex) { Logit.WriteError("Error converting USX files in " + usxDir + " to USFX."); Logit.WriteError(ex.Message); return(false); } return(result); }
/// <summary> /// Flush the hash table to an XML file ("save"). /// </summary> /// <returns>true iff success</returns> public bool Write() { XmlTextWriter xml = null; bool result = false; string bakFileName = Path.ChangeExtension(fileName, "bak"); try { Utils.DeleteFile(bakFileName); if (File.Exists(fileName)) { File.Move(fileName, bakFileName); } try { xml = new XmlTextWriter(fileName, System.Text.Encoding.UTF8); xml.WriteStartDocument(); xml.Formatting = Formatting.Indented; xml.WriteStartElement("ini"); IDictionaryEnumerator enu = hashTbl.GetEnumerator(); while (enu.MoveNext()) { xml.WriteStartElement("entry"); xml.WriteElementString("key", (string)enu.Key); xml.WriteElementString("value", (string)enu.Value); xml.WriteEndElement(); // entry } xml.WriteEndElement(); // ini xml.WriteEndDocument(); result = true; } finally { if (xml != null) { xml.Close(); } } } catch { Logit.WriteError("Can't write to " + fileName); } return(result); }
/// <summary> /// Convert all USX files with .usx extensions in the given usxDir and directories /// below it to USFX in usfxFile. (Scanning directories below it is to /// allow a pure unzip of an ETEN DBL bundle to be put into the USX directory. /// </summary> /// <param name="usxDir">Directory containing .usx files</param> /// <param name="usfxFile">path and file name of USFX file to write</param> /// <returns></returns> public bool Convert(string usxDir, string usfxFile) { try { processedUsxBooks = string.Empty; scrp = new Scriptures(); scrp.OpenUsfx(usfxFile); ScanUsxDir(usxDir); scrp.CloseUsfx(); } catch (Exception ex) { Logit.WriteError("Error converting USX files in " + usxDir + " to " + usfxFile); Logit.WriteError(ex.Message); return(false); } return(true); }
/// <summary> /// Figure out which lemma index file to write to. /// </summary> /// <param name="theWord">Strong's number (starting with capital H or G)</param> /// <returns>index into array of files</returns> protected int HashLemma(string theWord) { int hash = 0; while ((!Char.IsDigit(theWord[theWord.Length - 1])) && (theWord.Length > 2)) { theWord = theWord.Substring(0, theWord.Length - 1); } if (!Int32.TryParse(theWord.Substring(1), out hash)) { return(0); } hash = hash / 1000; if (theWord[0] == 'H') { hash += 6; } if (hash >= HASHSIZE) { Logit.WriteError("Bad Strong's number: " + theWord); hash = 0; } return(hash); }
/// <summary> /// Write title.json and info.json /// </summary> protected override void WriteContentsPage() { int i; bool needComma; StreamWriter infojson, titlejson; ChapterInfo ci; if (shortTitle == string.Empty) { shortTitle = englishDescription; } string lastBook = string.Empty; string countryArray; countryArray = "\"countries\":[\"" + countries.Replace(" ", "\",\"") + "\"]"; /* * switch (languageIdentifier) * { * case "cmn": * countryArray = "\"countries\": [\"CN\",\"HK\",\"MO\",\"TW\"]"; * break; * case "eng": * countryArray = "\"countries\":[\"AU\",\"CA\",\"GB\",\"NZ\",\"US\"]"; * break; * case "fra": * countryArray = "\"countries\":[\"BE\",\"CD\",\"CI\",\"CM\",\"FR\",\"HT\"]"; * break; * case "deu": * countryArray = "\"countries\":[\"AT\",\"BE\",\"CH\",\"DE\",\"LI\",\"LU\"]"; * break; * case "rus": * countryArray = "\"countries\":[\"BY\",\"KG\",\"KZ\",\"RU\",\"TJ\"]"; * break; * case "spa": * countryArray = "\"countries\": [\"AR\",\"BO\",\"CL\",\"CO\",\"CR\",\"CU\",\"DO\",\"EC\",\"ES\",\"HN\",\"MX\",\"NI\",\"PA\",\"PE\",\"PR\",\"PY\",\"SV\",\"UY\",\"VE\"]"; * break; * default: * countryArray = "\"countries\":[\"" + countries.Replace(" ", "\",\"") + "\"]"; * break; * } */ countryArray = countryArray + ",\n"; string allCountriesArray = "\"allcountries\":[\"" + countries.Replace(" ", "\",\"") + "\"],\n"; try { if (String.IsNullOrEmpty(traditionalAbbreviation)) { traditionalAbbreviation = translationIdentifier; } infojson = new StreamWriter(Path.Combine(htmDir, "info.json")); titlejson = new StreamWriter(Path.Combine(htmDir, "title.json")); infojson.Write("{\n"); infojson.Write("\"id\":\"{0}\",\n", translationIdentifier); infojson.Write("\"haiola_id\":\"{0}\",\n", translationIdentifier); infojson.Write("\"fcbh_id\":\"{0}\",\n", fcbhId); infojson.Write("\"type\":\"bible\",\n"); infojson.Write("\"name\":\"{0}\",\n", translationName); infojson.Write("\"nameEnglish\":\"{0}\",\n", shortTitle); if (projectOptions.hasStrongs) { infojson.Write("\"hasLemma\":true,\n"); } else { infojson.Write("\"hasLemma\":false,\n"); } infojson.Write("\"abbr\":\"{0}\",\n", traditionalAbbreviation); infojson.Write("\"dir\":\"{0}\",\n", textDirection); infojson.Write("\"lang\":\"{0}\",\n", languageIdentifier); infojson.Write("\"langName\":\"{0}\",\n", languageNameInVernacular); infojson.Write("\"langNameEnglish\":\"{0}\",\n", languageNameInEnglish); infojson.Write("\"fontClass\":\"{0}\",\n", fontClass); infojson.Write("\"script\":\"{0}\",\n", script); infojson.Write("\"dialectCode\":\"{0}\",\n", dialectCode); infojson.Write("\"audioDirectory\":\"{0}\",\n", fcbhId); infojson.Write("\"fcbh_drama_nt\":\"{0}\",\n", fcbhDramaNt); infojson.Write("\"fcbh_drama_ot\":\"{0}\",\n", fcbhDramaOt); infojson.Write("\"fcbh_audio_nt\":\"{0}\",\n", fcbhAudioNt); infojson.Write("\"fcbh_audio_ot\":\"{0}\",\n", fcbhAudioOt); infojson.Write("\"fcbh_portion\":\"{0}\",\n", fcbhPortion); infojson.Write(numbers + "\n"); infojson.Write("\"country\":\"{0}\",\n", country); infojson.Write("\"countryCode\":\"{0}\",\n", countryCode); infojson.Write(countryArray); infojson.Write(allCountriesArray); infojson.Write("\"stylesheet\":\"{0}\",\n", customCssName); infojson.Write("\"timeGenerated\":\"{0}\",\n", DateTime.UtcNow.ToString("s")); titlejson.Write("{\n"); titlejson.Write("\"id\":\"{0}\",\n", translationIdentifier); titlejson.Write("\"type\":\"bible\",\n"); titlejson.Write("\"name\":\"{0}\",\n", translationName); titlejson.Write("\"nameEnglish\":\"{0}\",\n", shortTitle); if (projectOptions.hasStrongs) { titlejson.Write("\"hasLemma\":true,\n"); } else { titlejson.Write("\"hasLemma\":false,\n"); } if (projectOptions.redistributable) { titlejson.Write("\"redistributable\":true,\n"); } else { titlejson.Write("\"redistributable\":false,\n"); } if (projectOptions.redistributable) { infojson.Write("\"redistributable\":true,\n"); } else { infojson.Write("\"redistributable\":false,\n"); } titlejson.Write("\"abbr\":\"{0}\",\n", traditionalAbbreviation); titlejson.Write("\"dir\":\"{0}\",\n", textDirection); titlejson.Write("\"lang\":\"{0}\",\n", languageIdentifier); titlejson.Write("\"country\":\"{0}\",\n", country); titlejson.Write(countryArray); titlejson.Write(allCountriesArray); titlejson.Write("\"langNameEnglish\":\"{0}\",\n", languageNameInEnglish); titlejson.Write("\"langName\":\"{0}\",\n", languageNameInVernacular); titlejson.Write("\"fontClass\":\"{0}\"\n", fontClass); titlejson.Write("}\n"); titlejson.Close(); needComma = false; infojson.Write("\"divisionNames\":["); for (i = 0; i < bookInfo.publishArrayCount; i++) { if (bookInfo.publishArray[i].IsPresent && (bookInfo.publishArray[i].chapterFiles != null) && (bookInfo.publishArray[i].chaptersFound.Count > 0)) { // This book is in the input files and contains at least one character of text. if (needComma) { infojson.Write(","); } infojson.Write("\"{0}\"", bookInfo.publishArray[i].vernacularShortName); needComma = true; } } infojson.Write("],\n"); needComma = false; infojson.Write("\"divisions\":["); for (i = 0; i < bookInfo.publishArrayCount; i++) { if (bookInfo.publishArray[i].IsPresent && (bookInfo.publishArray[i].chapterFiles != null) && (bookInfo.publishArray[i].chaptersFound.Count > 0)) { // This book is in the input files and contains at least one character of text. if (needComma) { infojson.Write(","); } infojson.Write("\"{0}\"", bookInfo.publishArray[i].shortCode); needComma = true; } } infojson.Write("],\n"); bool hasShortAbbreviations = true; StringBuilder sb = new StringBuilder("\"divisionAbbreviations\":["); needComma = false; for (i = 0; i < bookInfo.publishArrayCount; i++) { if (bookInfo.publishArray[i].IsPresent && (bookInfo.publishArray[i].chapterFiles != null) && (bookInfo.publishArray[i].chaptersFound.Count > 0)) { if (needComma) { sb.Append(","); } string abbr = bookInfo.publishArray[i].vernacularAbbreviation; if (abbr.Length < 3) { sb.Append(String.Format("\"{0}\"", abbr)); } else { hasShortAbbreviations = false; i = bookInfo.publishArrayCount; } needComma = true; } } sb.Append("],"); if (hasShortAbbreviations) { infojson.Write(sb.ToString() + "\n"); } needComma = false; infojson.Write("\"sections\":["); for (i = 0; i < bookInfo.allChapters.Count; i++) { ci = (ChapterInfo)bookInfo.allChapters[i]; if ((ci != null) && (ci.chapterId.Length > 2)) { if (needComma) { infojson.Write(","); if (ci.chapterId.Substring(0, 2) != lastBook) { infojson.Write("\n"); } } infojson.Write("\"{0}\"", ci.chapterId); } needComma = true; lastBook = ci.chapterId.Substring(0, 2); } infojson.Write("]\n}\n"); infojson.Close(); } catch (Exception err) { Logit.WriteError(err.Message + " writing contents files version.json and index.html in " + htmDir); Logit.WriteError(err.StackTrace); } }
public bool ConvertUsfxToSile(string usfxFileName, string sileDirectory) { bool result = false; sileDir = sileDirectory; usfx = new XmlTextReader(usfxFileName); usfx.WhitespaceHandling = WhitespaceHandling.All; while (usfx.Read()) { Logit.ShowStatus("converting to SILE " + cv); if (usfx.NodeType == XmlNodeType.Element) { level = usfx.GetAttribute("level"); style = usfx.GetAttribute("style"); sfm = usfx.GetAttribute("sfm"); caller = usfx.GetAttribute("caller"); id = usfx.GetAttribute("id"); switch (usfx.Name) { case "languageCode": SkipElement(); break; case "book": currentBookHeader = currentBookTitle = String.Empty; toc1 = toc2 = toc3 = String.Empty; inToc1 = inToc2 = inToc3 = false; currentChapter = currentChapterPublished = currentChapterAlternate = String.Empty; currentVerse = currentVersePublished = currentVerseAlternate = String.Empty; titleWritten = false; chapterWritten = false; if (id.Length > 2) { currentBookAbbrev = id; bookRecord = (BibleBookRecord)bookInfo.books[currentBookAbbrev]; } if ((bookRecord == null) || (id.Length <= 2)) { Logit.WriteError("Cannot process unknown book: " + currentBookAbbrev); return(false); } if ((bookRecord.testament == "a") && !globe.projectOptions.includeApocrypha) { SkipElement(); } else if (!globe.projectOptions.allowedBookList.Contains(bookRecord.tla)) // Check for presence of book in bookorder.txt { SkipElement(); } else { // We have a book we want to write out. OpenSileFile(); } break; case "fe": // End note. Rarely used, fortunately, but in the standards. Treat as regular footnote. case "f": // footnote if (!usfx.IsEmptyElement) { if (caller == "-") { caller = String.Empty; } else if ((caller == "+") || (String.IsNullOrEmpty(caller))) { caller = footnoteMark.Marker(); } sileFile.WriteStartElement("f"); sileFile.WriteAttributeString("caller", caller); } break; case "x": // Cross references if (!usfx.IsEmptyElement) { if (caller == "-") { caller = String.Empty; } else if ((caller == "+") || (String.IsNullOrEmpty(caller))) { caller = xrefMark.Marker(); } sileFile.WriteStartElement("x"); sileFile.WriteAttributeString("caller", caller); } break; case "ide": case "fm": // Should not actually be in any field texts. Safe to skip. case "idx": // Peripherals - Back Matter Index SkipElement(); break; case "ie": // Introduction end SkipElement(); break; case "id": if (id != currentBookAbbrev) { Logit.WriteError("Book ID in <id> and <book> do not match: " + currentBookAbbrev + " is not " + id); } SkipElement(); // Strip out comment portion. break; case "toc": // Table of Contents entries if (String.IsNullOrEmpty(level) || (level == "1")) { inToc1 = true; } else if (level == "2") { inToc2 = true; } else if (level == "3") { inToc3 = true; } else { SkipElement(); } break; case "rem": // Comment; not part of the actual text SkipElement(); break; case "h": currentBookHeader = ReadElementText().Trim(); break; case "c": currentChapter = id; currentChapterPublished = fileHelper.LocalizeDigits(currentChapter); currentChapterAlternate = String.Empty; currentVerse = currentVersePublished = currentVerseAlternate = String.Empty; currentChapterPublished = chapterLabel + fileHelper.LocalizeDigits(ReadElementText().Trim()); chapterWritten = false; break; case "cl": if (currentChapter == String.Empty) { chapterLabel = ReadElementText().Trim() + " "; } else { currentChapterPublished = ReadElementText().Trim(); } break; case "cp": if (!usfx.IsEmptyElement) { currentChapterPublished = ReadElementText().Trim(); } break; case "v": PrintChapter(); currentVersePublished = fileHelper.LocalizeDigits(id); currentVerse = id.Replace("\u200F", ""); // Strip out RTL character currentVerseAlternate = ""; if (!usfx.IsEmptyElement) { usfx.Read(); if (usfx.NodeType == XmlNodeType.Text) { currentVersePublished = fileHelper.LocalizeDigits(usfx.Value.Trim()); } if (usfx.NodeType != XmlNodeType.EndElement) { usfx.Read(); } } break; case "va": // Not supported by The Sword Project SkipElement(); break; case "vp": SkipElement(); /* This feature is not supported by The Sword Project. * if (!usfx.IsEmptyElement) * { * usfx.Read(); * if (usfx.NodeType == XmlNodeType.Text) * { * currentVersePublished = usfx.Value.Trim(); * if (currentVersePublished.Length > 0) * { * vpeID = StartId(); * StartMosisElement("verse"); * mosis.WriteAttributeString("osisID", osisVerseId); * mosis.WriteAttributeString("sID", verseeID); * mosis.WriteAttributeString("n", currentVersePublished); * WriteMosisEndElement(); // verse * } * } * } */ break; case "periph": SkipElement(); break; case "cs": // Rare or new character style: don't know what it should be, so throw away tag & keep text. break; case "gw": // Do nothing. Not sure what to do with glossary words, yet. case "xt": // Do nothing. case "ft": // Ignore. It does nothing useful, but is an artifact of USFM exclusive character styles. break; case "usfx": // Nothing to do, here. break; case "dc": case "xdc": case "fdc": if (!globe.projectOptions.includeApocrypha) { SkipElement(); } break; default: sileFile.WriteStartElement(usfx.Name); if (id != null) { sileFile.WriteAttributeString("id", id); } if (caller != null) { sileFile.WriteAttributeString("caller", caller); } if (level != null) { sileFile.WriteAttributeString("level", level); } if (sfm != null) { sileFile.WriteAttributeString("sfm", sfm); } if (style != null) { sileFile.WriteAttributeString("style", style); } if (usfx.IsEmptyElement) { sileFile.WriteEndElement(); } break; } } else if (usfx.NodeType == XmlNodeType.EndElement) { if (inToc1 || inToc2) { if (usfx.Name == "toc") { inToc2 = inToc1 = false; } else if (inToc1 && usfx.Name == "it") { toc1 += "</hi></seg>"; } else { Logit.WriteLine("Warning: " + usfx.Name + " end markup in title at " + currentBookAbbrev + " not written to OSIS file"); } } else { switch (usfx.Name) { case "w": case "zw": if (inStrongs) { WriteMosisEndElement(); inStrongs = false; } break; case "wj": WriteMosisEndElement(); // q break; case "book": EndLineGroup(); EndCurrentVerse(); EndCurrentChapter(); EndIntroduction(); EndMajorSection(); WriteMosisEndElement(); // div type="book" CheckElementLevel(3, "closed book"); break; case "bdit": WriteMosisEndElement(); // hi italic WriteMosisEndElement(); // hi bold break; case "p": if (itemLevel > 0) { itemLevel--; } CheckMinimumLevel(5, "Ending " + usfx.Name + " " + osisVerseId); inNote = false; if (eatPoetryLineEnd) { eatPoetryLineEnd = false; } else { WriteMosisEndElement(); } break; case "q": if (eatPoetryLineEnd) { eatPoetryLineEnd = false; } else { WriteMosisEndElement(); } break; case "ref": if (inReference) { WriteMosisEndElement(); // reference inReference = false; } break; case "fe": case "f": case "x": if (inNote) { inNote = false; WriteMosisEndElement(); // End of note } break; case "add": if (!inNote) { WriteMosisEndElement(); } break; case "qs": if (inLineGroup) { WriteMosisEndElement(); inPoetryLine = false; } break; case "bd": case "bk": case "cl": case "d": case "dc": case "em": case "fk": case "fp": case "fq": case "fqa": case "fr": case "fv": case "k": case "no": case "pn": case "qac": case "qt": case "r": case "rq": case "s": case "sc": case "sig": case "sls": case "table": case "tc": case "tcr": case "th": case "thr": case "tl": case "tr": case "xo": case "ord": // case "xq": Not useful for Sword modules. WriteMosisEndElement(); // note, hi, reference, title, l, transChange, etc. break; case "it": if (!inStrongs) { WriteMosisEndElement(); } break; case "nd": WriteMosisEndElement(); // divineName WriteMosisEndElement(); // seg break; case "xk": case "fl": case "zcr": case "zcb": case "zcg": case "zcy": // not supported. break; /* Can't get to this case (caught in "if" above) * case "toc": * inToc2 = inToc1 = false; * break;*/ } } } else if (((usfx.NodeType == XmlNodeType.Text) || (usfx.NodeType == XmlNodeType.SignificantWhitespace) || (usfx.NodeType == XmlNodeType.Whitespace)) && !ignore) { if (inToc1) { toc1 = toc1 + usfx.Value; } else if (inToc2) { toc2 = toc2 + usfx.Value; } else { mosis.WriteString(usfx.Value); } } } return(result); }
/// <summary> /// Read a USX file, convert to USFX, and append to a USFX file. /// </summary> /// <param name="UsxFileName">Name of one USX file to read</param> /// <returns>true iff the conversion worked</returns> protected bool ReadUsx(string UsxFileName) { int charNesting = 0; int noteCharNesting = 0; string style; string number; string code; string sfm; string level; string caller; string loc; string closed; string thisBook = String.Empty; string thisChapter = String.Empty; string thisVerse = String.Empty; bool badNoteCharSyntaxUsed = false; bool inNote = false; try { usx = new XmlTextReader(UsxFileName); usx.WhitespaceHandling = WhitespaceHandling.Significant; while (usx.Read()) { if (usx.NodeType == XmlNodeType.Element) { style = GetAnAttribute("style"); number = GetAnAttribute("number"); code = GetAnAttribute("code"); caller = GetAnAttribute("caller"); closed = GetAnAttribute("closed"); loc = GetAnAttribute("loc"); switch (usx.Name) { // TODO: Handle: rem, cl, cp, ca, va, vp case "usx": // Ignore this one and use </usx> to close the <book> tag. break; case "book": // In usfx, <book> is a container around a book. // In usx, <book> is encompasses only the \id line if (processedUsxBooks.Contains(code)) { usx.Close(); return(false); // Skipping book because we read it already in another canon set } processedUsxBooks += code + " "; // Keep track of books already processed. scrp.xw.WriteStartElement("book"); scrp.xw.WriteAttributeString("id", code); scrp.xw.WriteStartElement("id"); scrp.xw.WriteAttributeString("id", code); thisBook = code; thisChapter = thisVerse = "0"; CloseEmptyElement(); break; case "chapter": scrp.xw.WriteStartElement(style); scrp.xw.WriteAttributeString("id", number); thisChapter = number; thisVerse = "0"; CloseEmptyElement(); break; case "verse": number = number.Replace(',', '-'); // Paratext allows comma or dash as a separator in verse ranges. scrp.xw.WriteStartElement(style); scrp.xw.WriteAttributeString("id", number); thisVerse = number; CloseEmptyElement(); /* * if ((thisBook == "ACT") && (thisChapter == "11") && (thisVerse == "11")) * Logit.WriteLine("Acts 11:11"); */ break; case "note": scrp.xw.WriteStartElement(style); scrp.xw.WriteAttributeString("caller", caller); scrp.xw.WriteAttributeString("sfm", style); badNoteCharSyntaxUsed = false; inNote = true; CloseEmptyElement(); break; case "char": scrp.xw.WriteStartElement(style); if (!usx.IsEmptyElement) { if (inNote) { noteCharNesting++; } else { charNesting++; } } if ((closed == "false") && (usx.IsEmptyElement)) { badNoteCharSyntaxUsed = true; Logit.WriteError("Empty unclosed char element at " + thisBook + " " + thisChapter + ":" + thisVerse); } else { CloseEmptyElement(); } break; case "table": scrp.xw.WriteStartElement("table"); CloseEmptyElement(); break; case "row": scrp.xw.WriteStartElement(style); CloseEmptyElement(); break; case "cell": scrp.xw.WriteStartElement(style); CloseEmptyElement(); break; case "para": level = String.Empty; sfm = style; int lastDigitIndex = style.Length - 1; if (char.IsDigit(style[lastDigitIndex])) { level = style.Substring(lastDigitIndex); sfm = style.Substring(0, lastDigitIndex); } switch (sfm) { case "h": scrp.xw.WriteStartElement("h"); break; case "toc": if (level == String.Empty) { level = "1"; } scrp.xw.WriteStartElement("toc"); scrp.xw.WriteAttributeString("level", level); break; case "p": case "q": case "d": case "s": case "mt": scrp.xw.WriteStartElement(sfm); if (!String.IsNullOrEmpty(level)) { scrp.xw.WriteAttributeString("level", level); } break; case "restore": // Discard this paragraph: it is a useless comment, not USFM, meaningless for publishing, and deprecated in current Paratext use if (!usx.IsEmptyElement) { bool stillMore = true; while (stillMore && !(usx.NodeType == XmlNodeType.EndElement)) { stillMore = usx.Read(); } } break; default: scrp.xw.WriteStartElement("p"); scrp.xw.WriteAttributeString("sfm", sfm); if (!String.IsNullOrEmpty(level)) { scrp.xw.WriteAttributeString("level", level); } break; } CloseEmptyElement(); break; case "figure": scrp.xw.WriteStartElement(style); string s = GetAnAttribute("desc"); scrp.xw.WriteElementString("description", s); s = GetAnAttribute("file"); scrp.xw.WriteElementString("catalog", s); s = GetAnAttribute("size"); scrp.xw.WriteElementString("size", s); s = GetAnAttribute("loc"); scrp.xw.WriteElementString("location", s); s = GetAnAttribute("copy"); scrp.xw.WriteElementString("copyright", s); s = GetAnAttribute("ref"); scrp.xw.WriteElementString("reference", s); if (!usx.IsEmptyElement) { usx.Read(); if (usx.NodeType == XmlNodeType.Text) { scrp.xw.WriteElementString("caption", usx.Value); } else if (usx.NodeType == XmlNodeType.EndElement) { scrp.xw.WriteEndElement(); if (usx.Name != "figure") { Logit.WriteError("Unexpected tag after figure: " + usx.Name); } } else { Logit.WriteError("Unexpected node type reading caption of figure!"); } } CloseEmptyElement(); break; case "optbreak": scrp.xw.WriteStartElement("optionalLineBreak"); CloseEmptyElement(); break; case "ref": reftgt = usxLoc2usfxTgt(loc); if (reftgt.Length > 6) { scrp.xw.WriteStartElement("ref"); scrp.xw.WriteAttributeString("tgt", reftgt); } break; default: Logit.WriteError("Unrecognized USX element name: " + usx.Name); break; } } else if (usx.NodeType == XmlNodeType.EndElement) { if (usx.Name == "ref") { if (reftgt.Length > 6) { scrp.xw.WriteEndElement(); } } else { if (usx.Name == "char") { if (inNote) { noteCharNesting--; } else { charNesting--; } } if ((noteCharNesting < 0) || (charNesting < 0)) { Logit.WriteError(String.Format("Unexpected char nesting value: {0} normal {1} in notes", charNesting, noteCharNesting)); } if ((usx.Name == "note") && badNoteCharSyntaxUsed) { inNote = false; if (badNoteCharSyntaxUsed) { scrp.xw.WriteEndElement(); // Close the character style started with a milestone. Yukky syntax. badNoteCharSyntaxUsed = false; } } scrp.xw.WriteEndElement(); } } else if ((usx.NodeType == XmlNodeType.SignificantWhitespace) || (usx.NodeType == XmlNodeType.Whitespace) || (usx.NodeType == XmlNodeType.Text)) { scrp.xw.WriteString(usx.Value); } } usx.Close(); } catch (Exception ex) { Logit.WriteError("Error reading " + UsxFileName); Logit.WriteError(ex.Message); return(false); } return(true); }
/// <summary> /// Create an index of Strong's numbers (corresponding to the lemma or root word lexicon entry number). /// NOTE: Call MakeJsonIndex immediately before calling MakeLemmaIndex. /// </summary> /// <param name="lemmaTextFile"></param> /// <param name="lemmaDir"></param> public void MakeLemmaIndex(string lemmaTextFile, string lemmaDir) { string oneWord; string bookCode; searchTextXml = new XmlTextReader(lemmaTextFile); wordCollection = new Hashtable(19999); StreamWriter[] lemmaFiles; int i, j, lineLength; char ch; char defaultSourceLanguage = 'H'; Utils.EnsureDirectory(lemmaDir); BibleBookRecord br; try { // Read all references to Strong's numbers into wordCollection hash table. while (searchTextXml.Read()) { if ((searchTextXml.NodeType == XmlNodeType.Element) && (searchTextXml.Name == "v")) { bookCode = fileHelper.GetNamedAttribute(searchTextXml, "b"); currentBook = bookInfo.getShortCode(bookCode); br = (BibleBookRecord)bookInfo.books[bookCode]; if (br.testament == "o") { defaultSourceLanguage = 'H'; } else { defaultSourceLanguage = 'G'; } currentChapter = fileHelper.GetNamedAttribute(searchTextXml, "c"); startVerse = currentVerse = fileHelper.GetNamedAttribute(searchTextXml, "v"); // Verse numbers might be verse bridges, like "20-22" or simple numbers, like "20". i = currentVerse.IndexOf('-'); if (i > 0) { startVerse = startVerse.Substring(0, i); } verseID = currentBook + currentChapter + "_" + startVerse; if (!Logit.ShowStatus("Creating lemma index " + verseID)) { searchTextXml.Close(); return; } searchTextXml.Read(); if (includedVerses.Contains(verseID) && (searchTextXml.NodeType == XmlNodeType.Text)) { string s = searchTextXml.Value; for (i = 0; i < s.Length; i++) { if (!Char.IsWhiteSpace(s[i])) { if (word.Length == 0) { if (Char.IsDigit(s[i])) { word.Append(defaultSourceLanguage); } } word.Append(s[i]); } else { AddWordToLemma(); } } AddWordToLemma(); } } } searchTextXml.Close(); // Write search index with fewer files. bool[] commaNeeded = new bool[LEMMASIZE]; // Boolean variables are created with value "false" lemmaFiles = new StreamWriter[LEMMASIZE]; char srcLang = 'G'; for (i = 0, j = 0; i < LEMMASIZE; i++, j++) { if (i == 6) { srcLang = 'H'; j = 0; } lemmaFiles[i] = new StreamWriter(Path.Combine(lemmaDir, "_" + srcLang + j.ToString() + "000.json"), false, Encoding.UTF8); lemmaFiles[i].Write("{\n"); } // Also write combined search index for web server use //wordLocationFile = new StreamWriter(Path.Combine(searchDir, "search.json")); //wordLocationFile.WriteLine("{"); foreach (DictionaryEntry de in wordCollection) { oneWord = (string)de.Key; int hash = HashLemma(oneWord); string longString = (string)de.Value; sqlConcordance.WriteLine("INSERT INTO {0} VALUES (\"{1}\",\"{2}\");", concTableName, oneWord, longString); StringBuilder sb = new StringBuilder(); lineLength = 26 + oneWord.Length; for (i = 0; i < longString.Length; i++) { ch = longString[i]; if (ch == ',') { sb.Append("\","); lineLength += 2; if (lineLength > 100) { sb.Append("\n"); lineLength = 0; } sb.Append("\""); lineLength++; } else { sb.Append(ch); lineLength++; } } if (commaNeeded[hash]) { lemmaFiles[hash].Write(",\n"); } lemmaFiles[hash].Write("\"{0}\":[\"{1}\"]", oneWord, sb.ToString()); commaNeeded[hash] = true; if (!Logit.ShowStatus("Writing lemma index " + oneWord)) { return; } } for (i = 0; i < LEMMASIZE; i++) { lemmaFiles[i].Write("}\n"); lemmaFiles[i].Close(); } sqlConcordance.WriteLine("UNLOCK TABLES;"); sqlConcordance.Close(); } catch (Exception ex) { Logit.WriteError(ex.Message); } }
/// <summary> /// Read an imp or OSIS file and convert at least the main canonical text to USFX. /// </summary> /// <param name="infile">input imp or OSIS file name</param> /// <param name="outfile">output USFX file name</param> public void readImpOsis(string infile, string outfile) { string line; string inname = infile; string bookAbbr = String.Empty; string bcv = String.Empty; string bk; int currentChapter = 0; int currentVerse = 0; int c = 0; int v = 0; string id = String.Empty; string type = String.Empty; string osisID = String.Empty; string sID = String.Empty; string eID = String.Empty; string lemma = String.Empty; string morph = String.Empty; string added = String.Empty; string marker = String.Empty; string subType = String.Empty; string src = String.Empty; string savlm = String.Empty; string n = String.Empty; string who = String.Empty; StreamReader sr; try { sr = new StreamReader(infile, Encoding.UTF8); line = sr.ReadLine().TrimStart(); sr.Close(); if (line.StartsWith("$$$")) { inname = outfile + ".tMpXmL"; Logit.WriteLine("Converting imp file " + infile + " to imp xml file " + inname); ImpOsis2Xml(infile, inname); } else if (!line.StartsWith("<?xml version=\"1.0\"")) { Logit.WriteError("I don't know what to do with this file: " + infile); return; } xr = new XmlTextReader(inname); holyBooks.OpenUsfx(outfile); Logit.WriteLine("Converting from " + inname + " to USFX file " + outfile); while (xr.Read()) { if ((delayedVerse > 0) && (xr.Name != "milestone")) { if (!inParagraph) { StartNewParagraph("p"); } if (delayedVerse > 0) { WriteEmptyElementWithAttributes("v", "id", delayedVerse.ToString()); delayedVerse = 0; } RestartWJ(); delayedVerse = 0; } if (xr.NodeType == XmlNodeType.Element) { id = GetNamedAttribute("id"); type = GetNamedAttribute("type"); osisID = GetNamedAttribute("osisID"); sID = GetNamedAttribute("sID"); eID = GetNamedAttribute("eID"); lemma = GetNamedAttribute("lemma"); morph = GetNamedAttribute("morph"); added = GetNamedAttribute("added"); marker = GetNamedAttribute("marker"); who = GetNamedAttribute("who"); subType = GetNamedAttribute("subType"); src = GetNamedAttribute("src"); savlm = GetNamedAttribute("savlm"); n = GetNamedAttribute("n"); sfm = GetNamedAttribute("sfm"); switch (xr.Name) { case "header": SkipElement(); break; case "impxml": Logit.WriteLine("Parsing " + inname + " as imp xml."); break; case "osis": Logit.WriteLine("Parsing " + inname + " as OSIS"); break; case "book": StartBook(id); break; case "chapter": bcv = ParseOsisId(osisID, out bk, out c, out v); EndParagraph(); WriteEmptyElementWithAttributes("c", "id", c.ToString()); currentChapter = c; break; case "v": WriteEmptyElementWithAttributes("v", "id", id); break; case "p": StartNewParagraph("p", sfm); break; case "verse": if (eID.Length > 0) { SuspendWJ(); WriteEmptyElementWithAttributes("ve"); } else { bcv = ParseOsisId(osisID, out bk, out c, out v); if (c != currentChapter) { EndParagraph(); WriteEmptyElementWithAttributes("c", "id", c.ToString()); currentChapter = c; } delayedVerse = v; currentVerse = v; } break; case "transChange": holyBooks.xw.WriteStartElement("add"); break; case "div": switch (type) { case "book": bcv = ParseOsisId(osisID, out bk, out c, out v); StartBook(bk); break; case "colophon": StartNewParagraph("p", "ie"); break; } break; case "milestone": if ((type == "x-extra-p") || (type == "x-p")) { SuspendWJ(); StartNewParagraph("p"); if (marker.Length > 0) { holyBooks.xw.WriteString(marker + " "); } } break; case "w": lemma = (lemma + " " + savlm).Trim(); morph = (morph + " " + src).Trim(); wHasContent = (!xr.IsEmptyElement) && ((lemma.Length + morph.Length) > 0); if (wHasContent) { holyBooks.xw.WriteStartElement("w"); if (lemma.Length > 0) { holyBooks.xw.WriteAttributeString("s", lemma.Replace("strong:", "")); } if (morph.Length > 0) { holyBooks.xw.WriteAttributeString("m", morph.Trim()); } if (xr.IsEmptyElement) { holyBooks.xw.WriteEndElement(); } } else { // Otherwise, don't bother with the tag, because we really don't know semantically what it means. Logit.WriteLine("Warning: empty <w> element ignored at " + bcv); } break; case "title": switch (type) { case "main": StartNewParagraph("mt"); break; case "psalm": StartNewParagraph("d"); break; case "acrostic": StartNewParagraph("s"); break; case "chapter": if (!inParagraph) { StartNewParagraph("p"); } SkipElement(); break; } break; case "note": // type="study" if (type == "study") { holyBooks.xw.WriteStartElement("f"); holyBooks.xw.WriteAttributeString("caller", "+"); } else { SkipElement(); } break; case "divineName": holyBooks.xw.WriteStartElement("nd"); break; case "foreign": holyBooks.xw.WriteStartElement("tl"); if (n.Length > 0) { holyBooks.xw.WriteString(" " + n + " "); } break; case "ip": holyBooks.xw.WriteStartElement("p"); holyBooks.xw.WriteAttributeString("sfm", "ip"); break; case "q": if (marker != String.Empty) { Console.WriteLine("Unsupported marker in <q> at {0}: \"{1}\"", bcv, marker); } if (who == "Jesus") { StartWJ(); } break; } } else if (xr.NodeType == XmlNodeType.EndElement) { switch (xr.Name) { case "w": if (wHasContent) { holyBooks.xw.WriteEndElement(); } break; case "book": EndBook(); currentChapter = 0; break; case "divineName": case "transChange": case "foreign": case "note": case "ip": holyBooks.xw.WriteEndElement(); break; case "verse": // <ve /> SuspendWJ(); WriteEmptyElementWithAttributes("ve"); break; case "q": EndWJ(); break; case "title": EndParagraph(); break; case "p": EndParagraph(); break; } } else if (xr.NodeType == XmlNodeType.Text) { holyBooks.xw.WriteString(xr.Value); } else if (xr.NodeType == XmlNodeType.Whitespace) { holyBooks.xw.WriteWhitespace(xr.Value); } } holyBooks.CloseUsfx(); xr.Close(); } catch (Exception ex) { Logit.WriteError("Error at " + bcv); Logit.WriteError(ex.Message); Logit.WriteError(ex.StackTrace); } }
/// <summary> /// Turns a Crosswire mod2imp.exe "OSIS" output into an XML file. /// </summary> /// <param name="infile">File generated with mod2imp.exe</param> /// <param name="outfile">Intermediate XML file</param> public void ImpOsis2Xml(string infile, string outfile) { StreamReader sr; StreamWriter sw; string line; string trimmedLine; int c, v; string ch = "0"; //string lastCh = "0"; string vs = "0"; //string lastVs = "0"; string bcv; string lastBookAbbrev = String.Empty; currentBookAbbrev = String.Empty; bool inBook = false; bool inIntro = false; try { sr = new StreamReader(infile, Encoding.UTF8); sw = new StreamWriter(outfile, false, Encoding.UTF8); sw.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); sw.WriteLine("<impxml>"); line = sr.ReadLine().Replace("&c.", "&c."); while (line != null) { trimmedLine = line.Trim(); if (trimmedLine.Length > 0) { if (trimmedLine.StartsWith("$$$")) { if (!trimmedLine.Contains("[")) { currentBookAbbrev = ParseImpLocation(trimmedLine, out ch, out vs); if (lastBookAbbrev != currentBookAbbrev) { if (inBook) { sw.WriteLine("</book>"); } sw.WriteLine("<book id=\"{0}\">", currentBookAbbrev); lastBookAbbrev = currentBookAbbrev; inBook = true; } if ((!String.IsNullOrEmpty(vs)) && (vs == "0") && !inIntro) { sw.WriteLine("<p sfm=\"ip\">"); inIntro = true; } if ((!String.IsNullOrEmpty(vs)) && (vs != "0") && inIntro) { sw.WriteLine("</p>"); inIntro = false; } /* * if ((!String.IsNullOrEmpty(vs)) && (vs != "0")) * sw.WriteLine("<v id=\"{0}\"/>", vs); */ } } else if (trimmedLine.StartsWith("<verse")) { bcv = ExtractOsisId(line); bcv = ParseOsisId(bcv, out currentBookAbbrev, out c, out v); if (lastBookAbbrev != currentBookAbbrev) { if (inBook) { sw.WriteLine("</book>"); } sw.WriteLine("<book id=\"{0}\">", currentBookAbbrev); lastBookAbbrev = currentBookAbbrev; inBook = true; } sw.WriteLine(line); } else /*if (trimmedLine.StartsWith("<"))*/ { string temp = System.Text.RegularExpressions.Regex.Replace(line, "<div [^>]*>", ""); temp = System.Text.RegularExpressions.Regex.Replace(temp, "<chapter [^>]*eID=[^>]*>", "</p>"); temp = System.Text.RegularExpressions.Regex.Replace(temp, "lemma=\"Strong:", "lemma=\""); temp = System.Text.RegularExpressions.Regex.Replace(temp, "(<chapter [^>]*>)", "$1<p>"); sw.WriteLine(temp); } /* * else * { * sw.WriteLine("<ip>{0}</ip>", line); * } */ } line = sr.ReadLine(); if (line != null) { line = line.Replace("&c.", "&c."); } } if (inBook) { sw.WriteLine("</book>"); } sw.WriteLine("</impxml>"); sw.Close(); sr.Close(); } catch (Exception ex) { Logit.WriteError(ex.Message); } }
/// <summary> /// Write navigational links to get to another chapter from here. /// /// </summary> protected override void WriteNavButtons() { int i; int prevChapIndex = 0; string s = String.Empty; prevChapterLink = String.Empty; nextChapterLink = String.Empty; int chapNumSize; try { string formatString = FormatString(out chapNumSize); string firstChapterFile = FirstChapterFile(formatString); string thisBookName = currentBookHeader; if (currentBookHeader.Trim().Length == 0) { if (currentBookAbbrev == "CPR") { thisBookName = "^"; } else { thisBookName = String.Empty; } } CheckHomeLink(); if (bookListIndex >= 0) { if (currentChapter.Trim().Length == 0) { if (chapterNumber < 0) { currentChapter = "0"; } else { currentChapter = chapterNumber.ToString(); } } string chFile; int nextChapIndex = -1; for (i = 0; (i < chapterFileList.Count) && (nextChapIndex < 0); i++) { chFile = (string)chapterFileList[i]; int cn; if ((!String.IsNullOrEmpty(chFile)) && chFile.StartsWith(currentBookAbbrev) && (int.TryParse(chFile.Substring(chFile.Length - chapNumSize), out cn))) { if (cn == chapterNumber) { nextChapIndex = i + 1; prevChapIndex = i - 1; } } } if ((nextChapIndex >= chapterFileList.Count) || (nextChapIndex < 0)) { nextChapIndex = 0; } nextChapterLink = String.Format("{0}.htm", (string)chapterFileList[nextChapIndex]); if ((prevChapIndex >= 0) && (prevChapIndex < chapterFileList.Count)) { prevChapterLink = String.Format("{0}.htm", (string)chapterFileList[prevChapIndex]); } else { prevChapterLink = "index.htm"; } } else { nextChapterLink = String.Format("{0}.htm", (string)chapterFileList[0]); } if (currentBookAbbrev != "CPR") { navButtons = String.Format(@"<ul class='tnav'> <li><a href='index.htm'>{0}</a></li> <li><a href='{1}'><</a></li> <li><a href='{2}.htm'>{3}</a></li> <li><a href='{4}'>></a></li> </ul>", thisBookName, prevChapterLink, currentBookAbbrev, fileHelper.LocalizeDigits(currentChapter), nextChapterLink); } else { navButtons = String.Format(@"<ul class='tnav'> <li><a href='index.htm'>{0}</a></li> <li><a href='{1}'><</a></li> <li><a href='{2}'>></a></li> </ul>", thisBookName, prevChapterLink, nextChapterLink); } htm.WriteLine(navButtons); } catch (Exception ex) { Logit.WriteError("ERROR in usfx2MobileHtml::WriteNavButtons():"); Logit.WriteError(ex.Message); } }
private bool ReadIniFile(string fName) { XmlTextReader xml = null; string k = null; string v = null; string elementName = null; bool result = false; if (!File.Exists(fName)) { return(false); } try { xml = new XmlTextReader(fName); xml.WhitespaceHandling = WhitespaceHandling.None; xml.MoveToContent(); while (xml.Read()) { switch (xml.NodeType) { case XmlNodeType.Element: elementName = xml.Name; if (elementName == "entry") { k = v = ""; } break; case XmlNodeType.Text: if (elementName == "key") { k += xml.Value; } else if (elementName == "value") { v += xml.Value; } break; case XmlNodeType.EntityReference: if (elementName == "key") { k += xml.Value; } else if (elementName == "value") { v += xml.Value; } break; case XmlNodeType.EndElement: if (xml.Name == "entry") { hashTbl[k] = v; } break; } } result = true; } catch { Logit.WriteError("Bad input format in file " + fName + "; using defaults."); } finally { if (xml != null) { xml.Close(); } } return(result); }
/// <summary> /// Write an SQL file for MySQL from the VPL XML search text file. /// </summary> /// <param name="verseFileName">Name of the XML verse per line file.</param> /// <param name="translationId">Bible translation ID</param> /// <param name="sqlName">Name of the SQL file to write.</param> public void WriteSearchSql(string verseFileName, string translationId, string sqlName) { Hashtable verseDupCheck = new Hashtable(64007); string tableName = Path.GetFileNameWithoutExtension(sqlName).Replace('-', '_'); XmlTextReader searchTextXml = new XmlTextReader(verseFileName); string book, bk, ch, vs, startVerse, endVerse, verseID, verseText, canon_order; int i; int dup = 0; StreamWriter sqlFile = new StreamWriter(sqlName, false, System.Text.Encoding.UTF8); sqlFile.WriteLine("USE sofia;"); sqlFile.WriteLine("DROP TABLE IF EXISTS sofia.{0};", tableName); sqlFile.WriteLine(@"CREATE TABLE {0} ( verseID VARCHAR(16) NOT NULL PRIMARY KEY, canon_order VARCHAR(12) NOT NULL, book VARCHAR(3) NOT NULL, chapter VARCHAR(3) NOT NULL, startVerse VARCHAR(3) NOT NULL, endVerse VARCHAR(3) NOT NULL, verseText TEXT CHARACTER SET UTF8 NOT NULL) ENGINE=MyISAM;", tableName); sqlFile.WriteLine("LOCK TABLES {0} WRITE;", tableName); while (searchTextXml.Read()) { if ((searchTextXml.NodeType == XmlNodeType.Element) && (searchTextXml.Name == "v")) { book = fileHelper.GetNamedAttribute(searchTextXml, "b"); bk = bookInfo.getShortCode(book); ch = fileHelper.GetNamedAttribute(searchTextXml, "c"); vs = endVerse = startVerse = fileHelper.GetNamedAttribute(searchTextXml, "v"); // Verse numbers might be verse bridges, like "20-22" or simple numbers, like "20". i = vs.IndexOf('-'); if (i > 0) { startVerse = startVerse.Substring(0, i); if (vs.Length > i) { endVerse = vs.Substring(i + 1); } } verseID = bk + ch + "_" + startVerse; canon_order = ((BibleBookRecord)bookInfo.books[book]).sortOrder.ToString("000") + "_" + ch + "_" + startVerse; if (verseDupCheck[verseID] != null) { Logit.WriteError("Duplicate verse ID: " + verseID); dup++; verseID = verseID + "_" + dup.ToString(); } verseDupCheck[verseID] = vs; searchTextXml.Read(); if (searchTextXml.NodeType == XmlNodeType.Text) { verseText = searchTextXml.Value; sqlFile.WriteLine("INSERT INTO {0} VALUES (\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\",\"{7}\");", tableName, verseID, canon_order, book, ch, startVerse, endVerse, verseText.Replace("\"", "\\\"")); } } } searchTextXml.Close(); sqlFile.WriteLine("ALTER TABLE {0} ADD FULLTEXT(verseText);", tableName); sqlFile.WriteLine("UNLOCK TABLES;"); sqlFile.Close(); }
/// <summary> /// Reads a USFX file and prepares it for full text search (or concordance generation) /// by extracting only the canonical text within verses (and the canonical Psalm titles, /// which are prepended to verse 1 text), stripping out all formatting, footnotes, etc., /// and normalizing all white space to single spaces. These verse text strings are put /// into an XML file with one "v" element per verse, with book, chapter, and verse given /// in attributes b, c, and v, respectively. /// </summary> /// <param name="usfxFileName">Name of the USFX file to extract canonical text from</param> /// <param name="verseFileName">Name of XML unformatted verse text only file</param> /// <returns></returns> public bool Filter(string usfxFileName, string verseFileName) { string level = String.Empty; string style = String.Empty; string sfm = String.Empty; string caller = String.Empty; string id = String.Empty; string strongs = String.Empty; verseText = new StringBuilder(); lemmaText = new StringBuilder(); bool result = false; try { utf8encoding = new UTF8Encoding(false); vplFile = new StreamWriter(Path.ChangeExtension(verseFileName, ".vpltxt"), false, utf8encoding); lemmaFile = new XmlTextWriter(Path.ChangeExtension(verseFileName, ".lemma"), utf8encoding); lemmaFile.Formatting = Formatting.Indented; lemmaFile.WriteStartDocument(); lemmaFile.WriteStartElement("lemmaFile"); usfx = new XmlTextReader(usfxFileName); usfx.WhitespaceHandling = WhitespaceHandling.All; verseFile = new XmlTextWriter(verseFileName, utf8encoding); verseFile.Formatting = Formatting.Indented; verseFile.WriteStartDocument(); verseFile.WriteStartElement("verseFile"); while (usfx.Read()) { if (!Logit.ShowStatus("extracting search text " + currentPlace)) { return(false); } if (usfx.NodeType == XmlNodeType.Element) { level = fileHelper.GetNamedAttribute(usfx, "level"); style = fileHelper.GetNamedAttribute(usfx, "style"); sfm = fileHelper.GetNamedAttribute(usfx, "sfm"); caller = fileHelper.GetNamedAttribute(usfx, "caller"); id = fileHelper.GetNamedAttribute(usfx, "id"); switch (usfx.Name) { case "book": currentChapter = String.Empty; currentVerse = String.Empty; if (id.Length == 3) { currentBook = id; bookRecord = (BibleBookRecord)bookInfo.books[currentBook]; osisBook = bookRecord.osisName; BibleWorksBook = bookRecord.bibleworksCode; } if ((bookRecord == null) || (id.Length != 3)) { Logit.WriteError("Cannot process unknown book: " + currentBook); SkipElement(); } if (bookRecord.testament == "x") { // Skip peripherals. SkipElement(); } currentPlace = currentBook; break; case "id": if (id != currentBook) { Logit.WriteError("Book ID in <id> and <book> do not match; " + currentBook + " is not " + id); } SkipElement(); // Strip out comment portion. break; case "h": usfx.Read(); if (usfx.NodeType == XmlNodeType.Text) { bookRecord.vernacularShortName = usfx.Value.Trim(); } break; case "toc": usfx.Read(); if (usfx.NodeType == XmlNodeType.Text) { if (level == "1") { bookRecord.vernacularLongName = usfx.Value.Trim(); } else if (level == "2") { string sn = usfx.Value.Trim(); if ((bookRecord.vernacularShortName.Length < 2) || (sn.Length < bookRecord.vernacularShortName.Length)) { bookRecord.vernacularShortName = sn; } } } break; case "c": EndVerse(); // In case file lacks <ve /> elements. currentChapter = id; currentVerse = String.Empty; currentPlace = currentBook + "_" + currentChapter; SkipElement(); // Doesn't skip chapter, just the published chapter number, if present. break; case "v": EndVerse(); // In case file lacks <ve /> elements. inVerse = true; currentVerse = id; currentPlace = currentBook + "_" + currentChapter + "_" + currentVerse; SkipElement(); // Just in case there is a published verse number present. break; case "ve": EndVerse(); break; case "b": // blank line case "optionalLineBreak": case "qs": case "th": case "thr": case "tc": case "tcr": if (inVerse) { verseText.Append(' '); } break; case "d": // Make canonical psalm titles searchable inPsalmTitle = true; break; case "add": verseText.Append("["); break; case "nd": //verseText.Append("{"); break; case "languageCode": case "f": // footnote case "fe": // End note. Rarely used, fortunately, but in the standards. case "x": // Cross references case "glo": case "ide": case "fig": // figure case "fdc": case "fm": // Should not actually be in any field texts. Safe to skip. case "idx": // Peripherals - Back Matter Index case "ie": // Introduction end case "iex": // Introduction explanatory or bridge text case "fp": case "rem": // Comment; not part of the actual text case "cl": case "ca": case "vp": case "periph": case "milestone": case "rq": case "s": SkipElement(); break; case "w": strongs = fileHelper.GetNamedAttribute(usfx, "s"); if (!String.IsNullOrEmpty(strongs)) { lemmaText.Append(strongs + " "); } break; case "p": if (sfm.StartsWith("i")) { SkipElement(); } else { switch (sfm) { case "cd": case "intro": case "hr": // Horizontal rule not supported. Try a line break. case "ib": case "im": case "imq": case "imi": case "ip": case "ipi": case "ipq": case "ipr": case "mt": case "keyword": case "iq": case "imte": case "imt": case "is": case "iot": case "ior": case "io": case "ili": case "r": SkipElement(); break; } } break; } } else if (usfx.NodeType == XmlNodeType.EndElement) { switch (usfx.Name) { case "book": EndVerse(); // In case file lacks <ve /> elements. currentBook = currentChapter = currentVerse = String.Empty; break; case "d": inPsalmTitle = false; break; case "add": verseText.Append("]"); break; case "nd": // verseText.Append("}"); break; } } else if (usfx.NodeType == XmlNodeType.Text) { if (inVerse || inPsalmTitle) { verseText.Append(usfx.Value); } } else if ((usfx.NodeType == XmlNodeType.SignificantWhitespace) || (usfx.NodeType == XmlNodeType.Whitespace)) { if (inVerse || inPsalmTitle) { verseText.Append(" "); } } } Logit.ShowStatus("writing " + verseFileName); verseFile.WriteEndElement(); // verseFile lemmaFile.WriteEndElement(); // lemmaFile verseFile.Close(); lemmaFile.Close(); vplFile.Close(); usfx.Close(); result = true; } catch (Exception ex) { Logit.WriteError(ex.Message); } return(result); }
/// <summary> /// Reads a Paratext .ssf file and imports selected configuration items into our own Options object. /// </summary> /// <param name="projectOptions">Options object to update with data in the Paratext .ssf file.</param> /// <param name="ssfFileName">Full path to the Paratext .ssf file to update.</param> public void ReadParatextSsf(Options projectOptions, string ssfFileName) { string elementName, setting; try { if (!File.Exists(ssfFileName)) { return; } XmlTextReader ssf = new XmlTextReader(ssfFileName); ssf.WhitespaceHandling = WhitespaceHandling.Significant; ssf.MoveToContent(); while (ssf.Read()) { if ((ssf.NodeType == XmlNodeType.Element) && (ssf.Name != "ScriptureText")) { if (!ssf.IsEmptyElement) { elementName = ssf.Name; ssf.Read(); // Get content of element if ((ssf.NodeType == XmlNodeType.Text) && (!String.IsNullOrEmpty(ssf.Value))) { setting = ssf.Value; switch (elementName) { case "Encoding": if (setting != "65001") { Logit.WriteLine("Warning: Paratext encoding is not Unicode UTF-8 (" + setting + ") in " + ssfFileName); } break; case "EthnologueCode": if (projectOptions.languageId.Length < 3) { projectOptions.languageId = setting; } break; case "RangeIndicator": // verse range separator projectOptions.rangeSeparator = setting; break; case "SequenceIndicator": projectOptions.multiRefSameChapterSeparator = setting; break; case "ChapterVerseSeparator": projectOptions.CVSeparator = setting; break; case "ChapterRangeSeparator": projectOptions.multiRefDifferentChapterSeparator = setting; break; case "BookSequenceSeparator": projectOptions.BookSequenceSeparator = setting; break; case "ChapterNumberSeparator": projectOptions.ChapterNumberSeparator = setting; break; case "BookSourceForMarkerXt": projectOptions.BookSourceForMarkerXt = setting; break; case "BookSourceForMarkerR": projectOptions.BookSourceForMarkerR = setting; break; case "Guid": projectOptions.paratextGuid = setting; break; } } } } } ssf.Close(); projectOptions.Write(); } catch (Exception ex) { Logit.WriteError("Error reading Paratext options file " + ssfFileName + ": " + ex.Message); Logit.WriteError(ex.StackTrace); } }