/// <summary> /// Load XML file. /// </summary> /// <param name="xmlDoc">XmlDoc.</param> /// <param name="nsmgr">Nsmgr.</param> /// <param name="contentController">Content controller.</param> protected override void Load(XmlDocument xmlDoc, XmlNamespaceManager nsmgr, object contentController) { ContentControler lexiconContentController = contentController as ContentControler; Debug.Assert(contentController == null || lexiconContentController != null); if (lexiconContentController == null) { lexiconContentController = new ContentControler(); } Language language = Localor.StringToLanguage(xmlDoc.DocumentElement.Attributes["lang"].InnerText); if (!Language.Equals(Language.Neutral) && !language.Equals(Language)) { ErrorSet.Add(CommonError.NotConsistentLanguage, Language.ToString(), "initial one", language.ToString(), "lexicon"); } Language = language; if (xmlDoc.DocumentElement.Attributes["domain"] != null) { string domainTag = xmlDoc.DocumentElement.Attributes["domain"].InnerText; if (!string.IsNullOrEmpty(domainTag)) { DomainTag = domainTag; } } // Load current lexicon _items.Clear(); XmlNodeList wordNodes = xmlDoc.DocumentElement.SelectNodes("tts:w", nsmgr); foreach (XmlNode wordNode in wordNodes) { LoadLexicalItem(this, wordNode, nsmgr, lexiconContentController); } // Get baseline lexicon file path string baseLexiconFilePath = string.Empty; if (xmlDoc.DocumentElement.FirstChild != null && xmlDoc.DocumentElement.FirstChild.LocalName == "include" && xmlDoc.DocumentElement.FirstChild.Attributes["href"] != null) { BaseLexiconRelativeFilePath = xmlDoc.DocumentElement.FirstChild.Attributes["href"].InnerText; if (!string.IsNullOrEmpty(BaseLexiconRelativeFilePath)) { baseLexiconFilePath = Helper.GetFullPath(Path.GetDirectoryName(this.FilePath), BaseLexiconRelativeFilePath); } } if (!string.IsNullOrEmpty(baseLexiconFilePath) && File.Exists(baseLexiconFilePath)) { Lexicon baseLexicon = new Lexicon(); baseLexicon._isBaseline = true; // Load baseline lexicon baseLexicon.Load(baseLexiconFilePath, lexiconContentController); // Merge current lexicon and baseline lexicon foreach (var baseItem in baseLexicon.Items) { // We drop those items if they have "deleted" status when LoadLexicalItem(), // so there's no deleted words in both lexicons. // if this item isn't in current lexicon, add it into current lexicon if (!_items.ContainsKey(baseItem.Key)) { _items.Add(baseItem.Key, baseItem.Value); } //// if this item is already in current lexicon, keep current word item /*else { } */ } } }
/// <summary> /// Save lexicon into Xml writer. /// </summary> /// <param name="writer">Writer file to save into.</param> /// <param name="contentController">Content controller.</param> protected override void PerformanceSave(XmlWriter writer, object contentController) { ContentControler lexiconContentController = contentController as ContentControler; if (lexiconContentController == null) { lexiconContentController = new ContentControler(); } writer.WriteStartElement("lexiconWords", "http://schemas.microsoft.com/tts"); writer.WriteAttributeString("lang", Localor.LanguageToString(Language)); if (!string.IsNullOrEmpty(DomainTag)) { writer.WriteAttributeString("domain", DomainTag); } if (!string.IsNullOrEmpty(BaseLexiconRelativeFilePath)) { writer.WriteStartElement("include"); writer.WriteAttributeString("href", BaseLexiconRelativeFilePath); writer.WriteEndElement(); } IEnumerable<LexicalItem> lexiconItems = _items.Values; if (lexiconContentController.DontSaveBaselineLexicon) { lexiconItems = _items.Values.Where(p => p.Origin == LexiconOrigin.Current); } // Go through each lexicon item in the lexicon foreach (LexicalItem lexiconItem in lexiconItems) { if (!string.IsNullOrEmpty(DomainTag)) { lexiconItem.CleanAllDomainTags(); } lexiconItem.WriteToXml(writer); } writer.WriteEndElement(); }
/// <summary> /// Performance loading. /// </summary> /// <param name="reader">Stream reader.</param> /// <param name="contentController">Content controller.</param> protected override void PerformanceLoad(StreamReader reader, object contentController) { if (reader == null) { throw new ArgumentNullException("reader"); } ContentControler scriptContentController = new ContentControler(); if (contentController is ContentControler) { scriptContentController = contentController as ContentControler; } else if (contentController != null) { throw new ArgumentException("Invalid contentController type"); } XmlTextReader xmlTextReader = new XmlTextReader(reader); while (xmlTextReader.Read()) { if (xmlTextReader.NodeType == XmlNodeType.Element && xmlTextReader.Name == "script") { Language = Localor.StringToLanguage(xmlTextReader.GetAttribute("language")); string version = xmlTextReader.GetAttribute("version"); if (version != null) { _version = version; } string sayAs = xmlTextReader.GetAttribute("say-as"); if (sayAs != null) { _sayAs = sayAs; } string isSsml = xmlTextReader.GetAttribute("isssml"); if (!string.IsNullOrEmpty(isSsml)) { IsSsml = bool.Parse(isSsml); } } else if (xmlTextReader.NodeType == XmlNodeType.Element && xmlTextReader.Name == "comments") { if (scriptContentController.LoadComments) { _ttsXmlComments.Parse(xmlTextReader); _ttsXmlComments.Tag = this; } else { xmlTextReader.Skip(); } } else if (xmlTextReader.NodeType == XmlNodeType.Element && xmlTextReader.Name == "si") { ScriptItem scriptItem = null; try { scriptItem = LoadItem(xmlTextReader, scriptContentController, Language); scriptItem.ScriptFile = this; scriptItem.IsSsml = IsSsml; if (_itemDic.ContainsKey(scriptItem.Id)) { // don't allow duplicate ID ErrorSet.Add(ScriptError.DuplicateItemId, scriptItem.Id); } else { _items.Add(scriptItem); _itemDic.Add(scriptItem.Id, scriptItem); } } catch (InvalidDataException ex) { ErrorSet.Add(ScriptError.OtherErrors, "null", Helper.BuildExceptionMessage(ex)); } } } if (scriptContentController.LoadComments) { ParseDeletedItemsFromComments(Language); } }
/// <summary> /// Save script into Xml writer. /// </summary> /// <param name="writer">Writer file to save into.</param> /// <param name="contentController">Content controller.</param> protected override void PerformanceSave(XmlWriter writer, object contentController) { if (writer == null) { throw new ArgumentNullException("writer"); } ContentControler scriptContentController = new ContentControler(); if (contentController is ContentControler) { scriptContentController = contentController as ContentControler; } else if (contentController != null) { throw new ArgumentException("Invalid contentController type"); } WriteTo(writer, scriptContentController); }
/// <summary> /// Load one script word from the xmltextreader. /// </summary> /// <param name="reader">XmlTextReader.</param> /// <param name="contentController">ContentControler.</param> /// <param name="language">The language of the script.</param> /// <returns>ScriptWord that read.</returns> public static ScriptWord LoadWord(XmlTextReader reader, object contentController, Language language) { Debug.Assert(reader != null); ContentControler scriptContentController = new ContentControler(); if (contentController is ContentControler) { scriptContentController = contentController as ContentControler; } else if (contentController != null) { throw new ArgumentException("Invalid contentController type"); } ScriptWord word = new ScriptWord(language); // load attributes LoadWordAttributes(word, reader, language); // load syllables // remember that word can have no syllable list if (!reader.IsEmptyElement) { while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "syls") { while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "syl") { ScriptSyllable syllable = LoadSyllable(reader, language); syllable.Word = word; word.Syllables.Add(syllable); } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "syls") { break; } } } else if (reader.NodeType == XmlNodeType.Element && reader.Name == "acoustics") { word.Acoustics = new ScriptAcoustics(); word.Acoustics.ParseFromXml(reader); } else if (reader.NodeType == XmlNodeType.Element && reader.Name == "comments") { if (scriptContentController.LoadComments) { word.TtsXmlComments.Parse(reader); word.TtsXmlComments.Tag = word; } else { reader.Skip(); } } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "w") { break; } } } return word; }
/// <summary> /// Load one script named entity from the xml text reader. /// </summary> /// <param name="reader">The XML reader instance to read data from.</param> /// <param name="sentence">Script sentence.</param> /// <param name="scriptContentController">ContentControler.</param> /// <returns>ScriptNamedEntity instance that read.</returns> public static ScriptNamedEntity LoadNamedEntity(XmlTextReader reader, ScriptSentence sentence, ContentControler scriptContentController) { Debug.Assert(reader != null); Debug.Assert(scriptContentController != null); ScriptNamedEntity entity = new ScriptNamedEntity(); entity.Type = reader.GetAttribute("type"); entity.Text = reader.GetAttribute("v"); string pos = reader.GetAttribute("pos"); if (!string.IsNullOrEmpty(pos)) { entity.PosString = pos; } Debug.Assert(sentence.Words.Count > 0); int startIndex = int.Parse(reader.GetAttribute("s"), CultureInfo.InvariantCulture); int endIndex = int.Parse(reader.GetAttribute("e"), CultureInfo.InvariantCulture); Collection<ScriptWord> graphemeWords = sentence.TextWords; if (startIndex < 0 && startIndex >= graphemeWords.Count) { throw new InvalidDataException(Helper.NeutralFormat( "Invalid start index for sentence [{0}] : [{1}]", sentence.ScriptItem.GetSentenceId(sentence), startIndex)); } entity.Start = graphemeWords[startIndex]; if (endIndex < 0 || endIndex >= graphemeWords.Count) { throw new InvalidDataException(Helper.NeutralFormat( "Invalid end index for sentence [{0}] : [{1}]", sentence.ScriptItem.GetSentenceId(sentence), endIndex)); } entity.End = graphemeWords[endIndex]; return entity; }
/// <summary> /// Load one script item from the xmltextreader. /// </summary> /// <param name="reader">XmlTextReader.</param> /// <param name="contentController">ContentControler.</param> /// <param name="language">The language of the script.</param> /// <returns>ScriptItem that read.</returns> public static ScriptItem LoadItem(XmlTextReader reader, object contentController, Language language) { Debug.Assert(reader != null); ContentControler scriptContentController = new ContentControler(); if (contentController is ContentControler) { scriptContentController = contentController as ContentControler; } else if (contentController != null) { throw new ArgumentException("Invalid contentController type"); } ScriptItem item = new ScriptItem(language); // get id, domain and reading difficulty if (!string.IsNullOrEmpty(reader.GetAttribute("id"))) { item.Id = reader.GetAttribute("id"); } else { string message = "Script id value cannot be null."; throw new ArgumentException(message); } string domain = reader.GetAttribute("domain"); if (!string.IsNullOrEmpty(domain)) { item.Domain = ScriptItem.StringToDomainType(domain); } string frequency = reader.GetAttribute("frequency"); if (!string.IsNullOrEmpty(frequency)) { item.Frequency = int.Parse(frequency); } string score = reader.GetAttribute("difficulty"); if (!string.IsNullOrEmpty(score)) { item.ReadingDifficulty = double.Parse(score, CultureInfo.InvariantCulture); } // get the text and sentences if (!reader.IsEmptyElement) { while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "sent") { ScriptSentence sentence = LoadSentence(reader, scriptContentController, language); sentence.ScriptItem = item; item.Sentences.Add(sentence); } else if (reader.NodeType == XmlNodeType.Element && reader.Name == "text") { reader.Read(); item.Text = reader.Value; } else if (reader.NodeType == XmlNodeType.Element && reader.Name == "comments") { if (scriptContentController.LoadComments) { item.TtsXmlComments.Parse(reader); item.TtsXmlComments.Tag = item; } else { reader.Skip(); } } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "si") { break; } } } return item; }
/// <summary> /// Write script to xml. /// </summary> /// <param name="writer">XmlWriter.</param> /// <param name="scriptContentController">Content controller.</param> private void WriteTo(XmlWriter writer, ContentControler scriptContentController) { if (writer == null) { throw new ArgumentNullException("writer"); } if (scriptContentController == null) { throw new ArgumentNullException("scriptContentController"); } writer.WriteStartElement("script", "http://schemas.microsoft.com/tts"); writer.WriteAttributeString("language", Localor.LanguageToString(Language)); if (!string.IsNullOrEmpty(Version)) { writer.WriteAttributeString("version", Version); } if (!string.IsNullOrEmpty(SayAs)) { writer.WriteAttributeString("say-as", SayAs); } if (!string.IsNullOrEmpty(Category)) { writer.WriteAttributeString("category", Category); } if (IsSsml) { writer.WriteAttributeString("isssml", IsSsml.ToString().ToLowerInvariant()); } if (scriptContentController.SaveComments) { WriteDeletedItemToComments(); _ttsXmlComments.WriteToXml(writer); } Collection<string> invalidTexts = new Collection<string>(); for (int i = 0; i < Items.Count; ++i) { ScriptItem item = Items[i]; item.IsSsml = IsSsml; if (!string.IsNullOrEmpty(item.Text)) { if (XmlHelper.IsValidXMLText(item.Text)) { item.WriteToXml(writer, scriptContentController, Language); } else { // Save invalid text. ErrorSet.Add(ScriptError.InvalidXmlCharactersError, (i + 1).ToString(), item.Text); } } } writer.WriteEndElement(); }
/// <summary> /// Write deleted item to comments. /// </summary> private void WriteDeletedItemToComments() { if (TtsXmlComments.TtsXmlStatusDict.ContainsKey(DeletedItemStatusName)) { TtsXmlComments.TtsXmlStatusDict.Remove(DeletedItemStatusName); } foreach (ScriptItem scriptItem in _deletedItemsDict.Keys) { scriptItem.TtsXmlComments.Reset(); foreach (ScriptSentence sentence in scriptItem.Sentences) { sentence.TtsXmlComments.Reset(); sentence.DeletedWordsDict.Clear(); foreach (ScriptWord word in sentence.Words) { word.TtsXmlComments.Reset(); } } // Delete the sentence. StringBuilder sb = new StringBuilder(); using (XmlWriter sw = XmlWriter.Create(sb)) { XmlScriptFile.ContentControler contentControler = new ContentControler(); contentControler.SaveComments = true; scriptItem.WriteToXml(sw, contentControler, Language); sw.Flush(); _deletedItemsDict[scriptItem].OriginalValue = sb.ToString(); TtsXmlComments.AppendStatus(_deletedItemsDict[scriptItem], true); } } }
/// <summary> /// Parse deleted items from comments. /// </summary> /// <param name="scriptLanguage">Script language.</param> private void ParseDeletedItemsFromComments(Language scriptLanguage) { DeletedItemsDict.Clear(); if (_ttsXmlComments.TtsXmlStatusDict.ContainsKey(DeletedItemStatusName)) { foreach (TtsXmlStatus status in _ttsXmlComments.TtsXmlStatusDict[DeletedItemStatusName]) { using (StringReader sr = new StringReader(status.OriginalValue)) { XmlTextReader xtr = new XmlTextReader(sr); if (!xtr.IsEmptyElement) { while (xtr.Read()) { if (xtr.NodeType == XmlNodeType.Element && xtr.Name == "si") { XmlScriptFile.ContentControler controler = new ContentControler(); controler.LoadComments = true; ScriptItem scriptItem = LoadItem(xtr, controler, scriptLanguage); scriptItem.ScriptFile = this; DeletedItemsDict.Add(scriptItem, status); } } } } } } }
/// <summary> /// Load one sentence from the xml text reader. /// </summary> /// <param name="reader">XmlTextReader.</param> /// <param name="scriptContentController">ContentControler.</param> /// <param name="language">The language of the script.</param> /// <returns>Sentence that read.</returns> private static ScriptSentence LoadSentence(XmlTextReader reader, ContentControler scriptContentController, Language language) { Debug.Assert(reader != null); Debug.Assert(scriptContentController != null); ScriptSentence sentence = new ScriptSentence(language); // get sentence type string type = reader.GetAttribute("type"); if (!string.IsNullOrEmpty(type)) { sentence.SentenceType = ScriptSentence.StringToSentenceType(type); } // get sentence emotion type string emotion = reader.GetAttribute("emotion"); if (!string.IsNullOrEmpty(emotion)) { sentence.Emotion = ScriptSentence.StringToEmotionType(emotion); } // get the text and word list while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "text") { reader.Read(); sentence.Text = reader.Value; } else if (reader.NodeType == XmlNodeType.Element && reader.Name == "words") { while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "w") { ScriptWord word = LoadWord(reader, scriptContentController, language); word.Sentence = sentence; sentence.Words.Add(word); } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "words") { break; } } } else if (reader.NodeType == XmlNodeType.Element && reader.Name == "accept") { List<ScriptWord> acceptSent = new List<ScriptWord>(); while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "w") { ScriptWord acceptWord = LoadWord(reader, scriptContentController, language); acceptWord.Sentence = sentence; acceptSent.Add(acceptWord); } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "accept") { break; } } sentence.AcceptSentences.Add(acceptSent); } else if (reader.NodeType == XmlNodeType.Element && reader.Name == "nes") { while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element && reader.Name == "ne") { ScriptNamedEntity entity = LoadNamedEntity(reader, sentence, scriptContentController); sentence.NamedEntities.Add(entity); } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "nes") { break; } } } else if (reader.NodeType == XmlNodeType.Element && reader.Name == "comments") { if (scriptContentController.LoadComments) { sentence.TtsXmlComments.Parse(reader); sentence.TtsXmlComments.Tag = sentence; } else { reader.Skip(); } } else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "sent") { break; } } if (scriptContentController.LoadComments) { ParseDeletedWordsFromComments(sentence, language); } return sentence; }