public TextNodesString Convert(IXmlNode node) { _parseStrings = new List <TextNodesString>(); if (node.NodeType == IXmlNodeType.Text) { AddParseString(BuildParseString(new[] { node })); } else { FindParseStrings(node); } var result = new TextNodesString(); var sb = new StringBuilder(); var cursor = 0; foreach (var textNodesString in _parseStrings) { if (cursor > 0) { textNodesString.NodesInfo.ForEach(e => e.MoveBy(cursor)); } sb.Append(textNodesString.Value); result.NodesInfo.AddRange(textNodesString.NodesInfo); cursor = sb.Length; } result.Value = sb.ToString(); result.IsReadonly = node.IsReadonly; return(result); }
private TextNodesString BuildParseString(IEnumerable <IXmlNode> nodes) { var result = new TextNodesString(); var sb = new StringBuilder(); foreach (var node in nodes) { var textNode = node.GetTextNode(); if (string.IsNullOrEmpty(textNode.InnerXml)) { continue; } var nodeText = textNode.InnerXml.Replace(HtmlTags.Nbsp, " "); result.NodesInfo.Add(new TextNodeEntry() { Node = textNode, StartIndex = sb.Length, EndIndex = sb.Length + nodeText.Length - 1, CleanedText = nodeText }); sb.Append(nodeText); } result.Value = sb.ToString(); return(result); }
private void AddParseString(TextNodesString parseString) { if (string.IsNullOrEmpty(parseString.Value)) { return; } _parseStrings.Add(parseString); }
private void ParseTextNodes(TextNodesString parseString) { var index = 0; // чтобы анализировать с первого символа, так как теперь поддерживаем ещё и такие ссылки, как "5:6 - ..." var verseEntry = stringParser.TryGetVerse(parseString.Value, index); var skipNodes = 0; while (verseEntry.VersePointerFound) { var verseWasRecognized = verseRecognitionService.TryRecognizeVerse(verseEntry, docParseContext); if (!verseWasRecognized && configurationManager.UseCommaDelimiter && verseEntry.EntryType <= VerseEntryType.ChapterVerse) { verseEntry = stringParser.TryGetVerse(parseString.Value, index, index, false); verseWasRecognized = verseRecognitionService.TryRecognizeVerse(verseEntry, docParseContext); } if (verseWasRecognized) { var verseNode = FindNodeAndMoveVerseTextInOneNodeIfNotReadonly(parseString, verseEntry, ref skipNodes); if (!this.docParseContext.DocumentId.IsReadonly && !parseString.IsReadonly) { if (!NodeIsLink(verseNode.NodeEntry.Node.GetParentNode())) { InsertVerseLink(verseNode, verseEntry); } else { UpdateLinkNode(verseNode.NodeEntry.Node.GetParentNode(), verseEntry); } } paragraphContextEditor.ParseResult.VerseEntries.Add(verseEntry); paragraphContextEditor.SetLatestVerseEntry(verseEntry); } if (verseEntry.VersePointer.SubVerses.NotFoundVerses.Count > 0) { paragraphContextEditor.ParseResult.NotFoundVerses.AddRange(verseEntry.VersePointer.SubVerses.NotFoundVerses); } var prevIndex = index; index = verseEntry.EndIndex + 1; if (index < parseString.Value.Length - 1) { var leftBoundary = !verseWasRecognized && verseEntry.EntryType > VerseEntryType.ChapterVerse ? prevIndex : index; verseEntry = stringParser.TryGetVerse(parseString.Value, index, leftBoundary, configurationManager.UseCommaDelimiter); } else { break; } } }
/// <summary> /// /// </summary> /// <param name="parseString"></param> /// <param name="verseEntryInfo"></param> /// <param name="skipNodes">Чтобы не проверять строку с начала</param> /// <returns></returns> private VerseInNodeEntry FindNodeAndMoveVerseTextInOneNodeIfNotReadonly(TextNodesString parseString, VerseEntry verseEntryInfo, ref int skipNodes) { var result = new VerseInNodeEntry(); if (parseString.NodesInfo.Count > 1) { foreach (var nodeEntry in parseString.NodesInfo.Skip(skipNodes)) { if (result.NodeEntry == null) { if (nodeEntry.StartIndex <= verseEntryInfo.StartIndex && verseEntryInfo.StartIndex <= nodeEntry.EndIndex) { if (!nodeEntry.WasCleaned) { nodeEntry.Clean(); // то есть, если в этой ноде есть стих, тогда мы можем немного её почистить. Чтобы другие ноды не изменять. } result.NodeEntry = nodeEntry; result.StartIndex = verseEntryInfo.StartIndex - nodeEntry.StartIndex; result.EndIndex = (nodeEntry.EndIndex >= verseEntryInfo.EndIndex ? verseEntryInfo.EndIndex : nodeEntry.EndIndex) - nodeEntry.StartIndex; if (this.docParseContext.DocumentId.IsReadonly || parseString.IsReadonly) { break; } if (nodeEntry.EndIndex >= verseEntryInfo.EndIndex) { break; } } } else { if (!nodeEntry.WasCleaned) { nodeEntry.Clean(); } var moveCharsCount = (verseEntryInfo.EndIndex > nodeEntry.EndIndex ? nodeEntry.EndIndex : verseEntryInfo.EndIndex) - nodeEntry.StartIndex + 1; var verseTextPart = nodeEntry.Node.InnerXml.Substring(0, moveCharsCount); result.EndIndex += moveCharsCount; nodeEntry.StartIndex += moveCharsCount; // здесь может быть ситуация, когда Startindex > EndIndex. Когда нода была из одного символа. Похоже, что это нормально. Так как мы больше нигде не используем эти ноды. result.NodeEntry.Node.InnerXml += verseTextPart; nodeEntry.Node.InnerXml = nodeEntry.Node.InnerXml.Remove(0, moveCharsCount); if (verseEntryInfo.EndIndex <= nodeEntry.EndIndex) { break; } } skipNodes++; } } else { result.NodeEntry = parseString.NodesInfo.First(); result.StartIndex = verseEntryInfo.StartIndex; result.EndIndex = verseEntryInfo.EndIndex; if (!result.NodeEntry.WasCleaned) { result.NodeEntry.Clean(); } } return(result); }