public void TextNavigator_ReadEscapedUntil_3() { const string text = "AB["; TextNavigator navigator = new TextNavigator(text); navigator.ReadEscapedUntil('[', ']'); }
public ICompletionSource TryCreateCompletionSource(ITextBuffer textBuffer) { var projectExplorer = GetFromVsEnvironment(); var textNavigator = TextNavigator.GetTextStructureNavigator(textBuffer); return(new CompletionSource(textBuffer, textNavigator, projectExplorer)); }
public void TextNavigator_FromFile_2() { string fileName = Path.Combine(TestDataPath, "record.txt"); TextNavigator navigator = TextNavigator.FromFile(fileName, Encoding.UTF8); Assert.AreEqual('#', navigator.ReadChar()); }
public void TextNavigator_SkipNonWord_2() { TextNavigator navigator = new TextNavigator(". (<ABC"); Assert.IsTrue(navigator.SkipNonWord('<', '>')); Assert.AreEqual('<', navigator.ReadChar()); }
public void TextNavigator_Length_1() { const string text = "ABC"; TextNavigator navigator = new TextNavigator(text); Assert.AreEqual(text.Length, navigator.Length); }
public void TextNavigator_ReadUntil_3() { TextNavigator navigator = new TextNavigator("12345<.>"); string actual = navigator.ReadUntil("<.>"); Assert.AreEqual("12345", actual); Assert.AreEqual("<.>", navigator.PeekString(3)); Assert.AreEqual("<.>", navigator.GetRemainingText()); navigator = new TextNavigator("12345"); actual = navigator.ReadUntil("<.>"); Assert.IsNull(actual); navigator = new TextNavigator("12345<"); actual = navigator.ReadUntil("<.>"); Assert.IsNull(actual); navigator = new TextNavigator("12345<."); actual = navigator.ReadUntil("<.>"); Assert.IsNull(actual); navigator = new TextNavigator("12345<.6>"); actual = navigator.ReadUntil("<.>"); Assert.IsNull(actual); navigator = new TextNavigator("12345<.>67890"); actual = navigator.ReadUntil("<.>"); Assert.AreEqual("12345", actual); Assert.AreEqual("<.>", navigator.PeekString(3)); Assert.AreEqual("<.>67890", navigator.GetRemainingText()); navigator = new TextNavigator(string.Empty); Assert.IsNull(navigator.ReadUntil("<.>")); }
private static byte[] _ParseText ( TextReader reader ) { List <byte> table = new List <byte>(182); string text = reader.ReadToEnd(); TextNavigator navigator = new TextNavigator(text); while (true) { if (!navigator.SkipWhitespace()) { break; } string s = navigator.ReadInteger(); if (string.IsNullOrEmpty(s)) { throw new IrbisException("Bad Alphabet table"); } byte value = byte.Parse(s); table.Add(value); } if (table.Count < 1) { throw new IrbisException("Bad alphabet table"); } return(table.ToArray()); }
public void TextNavigator_Text_1() { string text = "ABC"; TextNavigator navigator = new TextNavigator(text); Assert.AreSame(text, navigator.Text); }
public void TextNavigator_ReadFrom_2() { const string text1 = "[ABC>DEF"; char[] open = { '[', '<' }, close = { '>', '>' }; TextNavigator navigator = new TextNavigator(text1); string actual = navigator.ReadFrom(open, close); Assert.AreEqual("[ABC>", actual); const string text2 = "[ABCDEF"; navigator = new TextNavigator(text2); actual = navigator.ReadFrom(open, close); Assert.AreEqual(string.Empty, actual); const string text3 = "ABC[DEF"; navigator = new TextNavigator(text3); actual = navigator.ReadFrom(open, close); Assert.AreEqual(string.Empty, actual); navigator = new TextNavigator(string.Empty); actual = navigator.ReadFrom(open, close); Assert.IsNull(actual); }
public void TextNavigator_SkipTo_1() { TextNavigator navigator = new TextNavigator("123ABC"); Assert.IsTrue(navigator.SkipTo('A')); Assert.AreEqual('A', navigator.ReadChar()); Assert.IsFalse(navigator.SkipTo('A')); }
public void TextNavigator_SkipChar_2() { TextNavigator navigator = new TextNavigator("123456"); Assert.IsTrue(navigator.SkipChar(3)); Assert.AreEqual('4', navigator.ReadChar()); Assert.IsFalse(navigator.SkipChar(3)); Assert.IsTrue(navigator.IsEOF); }
public void TextNavigator_SplitToWords_1() { TextNavigator navigator = new TextNavigator("Hello, world!"); string[] result = navigator.SplitToWords(); Assert.AreEqual(2, result.Length); Assert.AreEqual("Hello", result[0]); Assert.AreEqual("world", result[1]); }
public void TextNavigator_SkipRange_1() { TextNavigator navigator = new TextNavigator("123ABC"); Assert.IsTrue(navigator.SkipRange('0', '9')); Assert.AreEqual('A', navigator.ReadChar()); navigator.Move(2); Assert.IsFalse(navigator.SkipRange('0', '9')); }
public static Parameter[] ParseString ( [NotNull] string text ) { Sure.NotNull(text, nameof(text)); List <Parameter> result = new List <Parameter>(); TextNavigator navigator = new TextNavigator(text); navigator.SkipWhitespace(); while (!navigator.IsEOF) { while (true) { bool flag = false; if (navigator.IsWhiteSpace()) { flag = true; navigator.SkipWhitespace(); } if (navigator.PeekChar() == ValueSeparator) { flag = true; navigator.SkipChar(ValueSeparator); } if (!flag) { break; } } string name = navigator.ReadEscapedUntil ( EscapeCharacter, NameSeparator ); if (ReferenceEquals(name, null)) { break; } name = name.Trim(); navigator.SkipWhitespace(); string value = navigator.ReadEscapedUntil ( EscapeCharacter, ValueSeparator ); Parameter parameter = new Parameter(name, value); result.Add(parameter); } return(result.ToArray()); }
public void TextNavigator_SkipWhile_1() { TextNavigator navigator = new TextNavigator("111ABC"); Assert.IsTrue(navigator.SkipWhile('1')); Assert.AreEqual('A', navigator.ReadChar()); navigator.Move(2); Assert.IsFalse(navigator.SkipWhile('1')); }
public void TextNavigator_Column_1() { const string text = "ABC"; TextNavigator navigator = new TextNavigator(text); Assert.AreEqual(1, navigator.Column); navigator.ReadChar(); Assert.AreEqual(2, navigator.Column); }
public void TextNavigator_SavePosition_1() { TextNavigator navigator = new TextNavigator("Hello, world!"); TextPosition saved = navigator.SavePosition(); Assert.AreEqual(navigator.Position, saved.Position); Assert.AreEqual(navigator.Line, saved.Line); Assert.AreEqual(navigator.Column, saved.Column); }
public void TextNavigator_ReadString_1() { const string text = "ABCDEF"; TextNavigator navigator = new TextNavigator(text); Assert.AreEqual("ABC", navigator.ReadString(3)); Assert.AreEqual("DEF", navigator.ReadString(4)); Assert.IsNull(navigator.ReadString(3)); }
public void TextNavigator_ReadWhile_1() { TextNavigator navigator = new TextNavigator("111234"); Assert.AreEqual("111", navigator.ReadWhile('1')); Assert.AreEqual(string.Empty, navigator.ReadWhile('1')); navigator.Move(3); Assert.IsNull(navigator.ReadWhile('1')); }
public void TextNavigator_ReadLine_1() { const string text = "ABC\r\nDEF"; TextNavigator navigator = new TextNavigator(text); Assert.AreEqual("ABC", navigator.ReadLine()); Assert.AreEqual("DEF", navigator.ReadLine()); Assert.IsNull(navigator.ReadLine()); }
public void TextNavigator_SkipControl_1() { TextNavigator navigator = new TextNavigator("\t\tABC"); Assert.IsTrue(navigator.SkipControl()); Assert.AreEqual('A', navigator.ReadChar()); navigator.Move(2); Assert.IsFalse(navigator.SkipControl()); }
public void TextNavigator_SkipPunctuation_1() { TextNavigator navigator = new TextNavigator(".,ABC"); Assert.IsTrue(navigator.SkipPunctuation()); Assert.AreEqual('A', navigator.ReadChar()); navigator.Move(2); Assert.IsFalse(navigator.SkipPunctuation()); }
public void TextNavigator_SkipChar_1() { TextNavigator navigator = new TextNavigator("111234"); Assert.IsTrue(navigator.SkipChar('1')); Assert.IsTrue(navigator.SkipChar('1')); Assert.IsTrue(navigator.SkipChar('1')); Assert.AreEqual('2', navigator.ReadChar()); Assert.IsFalse(navigator.SkipChar('1')); }
public void TextNavigator_SplitByGoodCharacters_1() { char[] good = { 'A', 'B', 'C', 'a', 'b', 'c' }; TextNavigator navigator = new TextNavigator("HELLOaworldBc!"); string[] result = navigator.SplitByGoodCharacters(good); Assert.AreEqual(2, result.Length); Assert.AreEqual("a", result[0]); Assert.AreEqual("Bc", result[1]); }
public void TextNavigator_ReadTo_2() { char[] stop = { ']', '>' }; TextNavigator navigator = new TextNavigator("ABC]>DEF"); Assert.AreEqual("ABC]", navigator.ReadTo(stop)); Assert.AreEqual(">", navigator.ReadTo(stop)); Assert.AreEqual("DEF", navigator.ReadTo(stop)); Assert.IsNull(navigator.ReadTo(stop)); }
public void TextNavigator_SplitToWords_2() { char[] additional = { '<', '>' }; TextNavigator navigator = new TextNavigator("<Hello>, world!"); string[] result = navigator.SplitToWords(additional); Assert.AreEqual(2, result.Length); Assert.AreEqual("<Hello>", result[0]); Assert.AreEqual("world", result[1]); }
public void TextNavigator_ReadEscapedUntil_2() { const string text = "AB[tC"; TextNavigator navigator = new TextNavigator(text); string expected = "ABtC"; string actual = navigator.ReadEscapedUntil('[', ']'); Assert.AreEqual(expected, actual); Assert.AreEqual(TextNavigator.EOF, navigator.ReadChar()); }
public void TextNavigator_SkipChar_3() { char[] allowed = { '1', '2' }; TextNavigator navigator = new TextNavigator("123456"); Assert.IsTrue(navigator.SkipChar(allowed)); Assert.IsTrue(navigator.SkipChar(allowed)); Assert.IsFalse(navigator.SkipChar(allowed)); Assert.AreEqual('3', navigator.ReadChar()); }
public void TextNavigator_Move_1() { const string text = "ABC"; TextNavigator navigator = new TextNavigator(text); Assert.AreSame(navigator, navigator.Move(2)); Assert.AreEqual(2, navigator.Position); Assert.AreSame(navigator, navigator.Move(-2)); Assert.AreEqual(0, navigator.Position); }
public void TextNavigator_SkipWhile_2() { char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; TextNavigator navigator = new TextNavigator("314ABC"); Assert.IsTrue(navigator.SkipWhile(digits)); Assert.AreEqual('A', navigator.ReadChar()); navigator.Move(2); Assert.IsFalse(navigator.SkipWhile(digits)); }
public JObject ParseDocument(string html) { JObject obj = null; html = System.Text.RegularExpressions.Regex.Replace(html, "(<script.*?>(.|\n)*?</script>)|(<style.*?>(.|\n)*?</style>)|(<!--.*?-->)", ""); TextNavigator sc = new TextNavigator(html); sc.TrimStart(); if (sc.StartsWith("<")) { obj = new JObject(); while (!sc.IsAtEnd) { this.ParseNode(sc, obj); } } return obj; }
private string ParseName(TextNavigator sc) { sc.TrimStart(); string name = null; string n = string.Empty; string ns = string.Empty; for (int i = sc.Index; i < sc.Value.Length; i++) { if (IsValidTagChar(sc.Value[i])) { n += sc.Value[i]; } else if (n == string.Empty && sc.Value[i] == ' ') { } else if (i > 0) { if (sc.Value[i] == ':' && n != string.Empty && ns == string.Empty) { ns = n; n = string.Empty; } else if (sc.Value[i] == ' ' || sc.Value[i] == '=' || sc.Value[i] == '>' || sc.Value[i] == '/' || sc.Value[i] == '\r' || sc.Value[i] == '\n') { sc.Index = i; break; } else { n = string.Empty; sc.Index = i; break; } } else { throw new Exception("Invalid Name."); } } if (n != string.Empty) name = (string.IsNullOrEmpty(ns) ? "" : ns + ":") + n; //sc.TrimStart(); return name; }
private JProperty ParseAttribute(TextNavigator sc) { sc.TrimStart(); JProperty att = null; string name = null; if (IsValidTagChar(sc.StartValue)) name = ParseName(sc); if (name != null) { sc.TrimStart(); if (sc.StartValue == '=') { sc.Index++; sc.TrimStart(); string val = string.Empty; Nullable<char> quotesSign = ((sc.StartValue == '\"' || sc.StartValue == '\'') ? (Nullable<char>)sc.StartValue : null); for (int i = (sc.Index + (quotesSign.HasValue ? 1 : 0)); i < sc.Value.Length; i++) { if (quotesSign.HasValue) { if (sc.Value[i] == quotesSign.Value) { sc.Index = i + 1; break; } else { val += sc.Value[i]; } } else { if (sc.Value[i] == ' ' || sc.Value[i] == '>' || sc.Value[i] == '\r' || sc.Value[i] == '\n') { sc.Index = i; break; } else { val += sc.Value[i]; } } } att = new JProperty(name, this.DecodeXml(val)); } else { } } else { sc.Index++; } sc.TrimStart(); return att; }
// moves an endpoint forward a certain number of units. // the endpoint is just an index into the text so it could represent either // the endpoint. private int MoveEndpointForward(int index, TextUnit unit, int count, out int moved) { switch (unit) { case TextUnit.Character: { int limit = _provider.GetTextLength() ; ValidateEndpoints(); moved = Math.Min(count, limit - index); index = index + moved; index = index > limit ? limit : index; } break; case TextUnit.Word: { string text = _provider.GetText(); ValidateEndpoints(); #if WCP_NLS_ENABLED // use the same word breaker as Avalon Text. WordBreaker breaker = new WordBreaker(); TextContainer container = new TextContainer(text); TextNavigator navigator = new TextNavigator(index, container); // move forward one word break for each count for (moved = 0; moved < count && index < text.Length; moved++) { if (!breaker.MoveToNextWordBreak(navigator)) break; } index = navigator.Position; #else for (moved = 0; moved < count && index < text.Length; moved++) { for (index++; !AtWordBoundary(text, index); index++) ; } #endif } break; case TextUnit.Line: { // figure out what line we are on. if we are in the middle of a line and // are moving left then we'll round up to the next line so that we move // to the beginning of the current line. int line = _provider.LineFromChar(index); // limit the number of lines moved to the number of lines available to move // Note lineMax is always >= 1. int lineMax = _provider.GetLineCount(); moved = Math.Min(count, lineMax - line - 1); if (moved > 0) { // move the endpoint to the beginning of the destination line. index = _provider.LineIndex(line + moved); } else if (moved == 0 && lineMax == 1) { // There is only one line so get the text length as endpoint index = _provider.GetTextLength(); moved = 1; } } break; case TextUnit.Paragraph: { // just like moving words but we look for paragraph boundaries instead of // word boundaries. string text = _provider.GetText(); ValidateEndpoints(); for (moved = 0; moved < count && index < text.Length; moved++) { for (index++; !AtParagraphBoundary(text, index); index++) ; } } break; case TextUnit.Format: case TextUnit.Page: case TextUnit.Document: { // since edit controls are plain text moving one uniform format unit will // take us all the way to the end of the document, just like // "pages" and document. int limit = _provider.GetTextLength(); ValidateEndpoints(); // we'll move 1 format unit if we aren't already at the end of the // document. Otherwise, we won't move at all. moved = index < limit ? 1 : 0; index = limit; } break; default: throw new System.ComponentModel.InvalidEnumArgumentException("unit", (int)unit, typeof(TextUnit)); } return index; }
void ITextRangeProvider.ExpandToEnclosingUnit(TextUnit unit) { Misc.SetFocus(_provider._hwnd); switch (unit) { case TextUnit.Character: // if it is a degenerate range then expand it to be one character. // otherwise, leave it as it is. if (Start == End) { int moved; End = MoveEndpointForward(End, TextUnit.Character, 1, out moved); } break; case TextUnit.Word: { // this works same as paragraph except we look for word boundaries instead of paragraph boundaries. // get the text so we can figure out where the boundaries are string text = _provider.GetText(); ValidateEndpoints(); #if WCP_NLS_ENABLED // use the same word breaker that Avalon Text uses. WordBreaker breaker = new WordBreaker(); TextContainer container = new TextContainer(text); // if the starting point of the range is not already at a word break // then move it backwards to the nearest word break. TextNavigator startNavigator = new TextNavigator(Start, container); if (!breaker.IsAtWordBreak(startNavigator)) { breaker.MoveToPreviousWordBreak(startNavigator); Start = startNavigator.Position; } // if the range is degenerate or the ending point of the range is not already at a word break // then move it forwards to the nearest word break. TextNavigator endNavigator = new TextNavigator(End, container); if (Start==End || !breaker.IsAtWordBreak(endNavigator)) { breaker.MoveToNextWordBreak(endNavigator); End = endNavigator.Position; } #else // move start left until we reach a word boundary. for (; !AtWordBoundary(text, Start); Start--) ; // move end right until we reach word boundary (different from Start). End = Math.Min(Math.Max(End, Start + 1), text.Length); for (; !AtWordBoundary(text, End); End++) ; #endif } break; case TextUnit.Line: { if (_provider.GetLineCount() != 1) { int startLine = _provider.LineFromChar(Start); int endLine = _provider.LineFromChar(End); MoveTo(_provider.LineIndex(startLine), _provider.LineIndex(endLine + 1)); } else { MoveTo(0, _provider.GetTextLength()); } } break; case TextUnit.Paragraph: { // this works same as paragraph except we look for word boundaries instead of paragraph boundaries. // get the text so we can figure out where the boundaries are string text = _provider.GetText(); ValidateEndpoints(); // move start left until we reach a paragraph boundary. for (; !AtParagraphBoundary(text, Start); Start--); // move end right until we reach a paragraph boundary (different from Start). End = Math.Min(Math.Max(End, Start + 1), text.Length); for (; !AtParagraphBoundary(text, End); End++); } break; case TextUnit.Format: case TextUnit.Page: case TextUnit.Document: MoveTo(0, _provider.GetTextLength()); break; //break; default: throw new System.ComponentModel.InvalidEnumArgumentException("unit", (int)unit, typeof(TextUnit)); } }
// moves an endpoint backward a certain number of units. // the endpoint is just an index into the text so it could represent either // the endpoint. private int MoveEndpointBackward(int index, TextUnit unit, int count, out int moved) { switch (unit) { case TextUnit.Character: { int limit = _provider.GetTextLength(); ValidateEndpoints(); int oneBasedIndex = index + 1; moved = Math.Max(count, -oneBasedIndex); index = index + moved; index = index < 0 ? 0 : index; } break; case TextUnit.Word: { string text = _provider.GetText(); ValidateEndpoints(); #if WCP_NLS_ENABLED // use the same word breaker as Avalon Text. WordBreaker breaker = new WordBreaker(); TextContainer container = new TextContainer(text); TextNavigator navigator = new TextNavigator(index, container); // move backward one word break for each count for (moved = 0; moved > count && index > 0; moved--) { if (!breaker.MoveToPreviousWordBreak(navigator)) break; } index = navigator.Position; #else for (moved = 0; moved > count && index > 0; moved--) { for (index--; !AtWordBoundary(text, index); index--) ; } #endif } break; case TextUnit.Line: { // Note count < 0. // Get 1-based line. int line = _provider.LineFromChar(index) + 1; int lineMax = _provider.GetLineCount(); // Truncate the count to the number of available lines. int actualCount = Math.Max(count, -line); moved = actualCount; if (actualCount == -line) { // We are moving by the maximum number of possible lines, // so we know the resulting index will be 0. index = 0; // If a line other than the first consists of only "\r\n", // you can move backwards past this line and the position changes, // hence this is counted. The first line is special, though: // if it is empty, and you move say from the second line back up // to the first, you cannot move further; however if the first line // is nonempty, you can move from the end of the first line to its // beginning! This latter move is counted, but if the first line // is empty, it is not counted. // Recalculate the value of "moved". // The first line is empty if it consists only of // a line separator sequence. bool firstLineEmpty = ((lineMax > 1 && _provider.LineIndex(1) == _lineSeparator.Length) || lineMax == 0); if (moved < 0 && firstLineEmpty) { ++moved; } } else // actualCount > -line { // Move the endpoint to the beginning of the following line, // then back by the line separator length to get to the end // of the previous line, since the Edit control has // no method to get the character index of the end // of a line directly. index = _provider.LineIndex(line + actualCount) - _lineSeparator.Length; } } break; case TextUnit.Paragraph: { // just like moving words but we look for paragraph boundaries instead of // word boundaries. string text = _provider.GetText(); ValidateEndpoints(); for (moved = 0; moved > count && index > 0; moved--) { for (index--; !AtParagraphBoundary(text, index); index--) ; } } break; case TextUnit.Format: case TextUnit.Page: case TextUnit.Document: { // since edit controls are plain text moving one uniform format unit will // take us all the way to the beginning of the document, just like // "pages" and document. // we'll move 1 format unit if we aren't already at the beginning of the // document. Otherwise, we won't move at all. moved = index > 0 ? -1 : 0; index = 0; } break; default: throw new System.ComponentModel.InvalidEnumArgumentException("unit", (int)unit, typeof(TextUnit)); } return index; }
private KeyValuePair<string, JToken> ParseNode(TextNavigator tn, JObject parent) { tn.TrimStart(); if (tn.StartValue == '<') { string name = null; JToken node = null; bool isComment = false; bool isDeclaration = false; #region "Start Tag: Name, Declaration, Comment" tn.Index = tn.Index + 1; int breakOff = 0; if (tn.StartsWith("?xml")) { //Declaration isDeclaration = true; tn.Index += 4; } else if (tn.StartValue == '!') { //Comment isComment = true; if (tn.Value[tn.Index + 1] == '-') breakOff = 1; if (tn.Value[tn.Index + 2] == '-') breakOff = 2; tn.Index += breakOff + 1; tn.TrimStart(); } else if (IsValidTagChar(tn.StartValue)) { //Name name = ParseName(tn); if (name != null) { node = new JObject(); } else { throw new Exception("Invalid Node Name."); } } else { throw new Exception("Invalid Node Name."); } #endregion if (node != null || isComment || isDeclaration) { var attNames = new List<string>(); bool elementAtEnd = false; if (name == "br") { elementAtEnd = true; node = null; } #region "Attributes, Declaration, Comment" //Declaration, Attributes, Comment string comment = string.Empty; string declVer = string.Empty; string declEnc = string.Empty; string declSta = string.Empty; for (int i = tn.Index; i < tn.Value.Length; i++) { if (!isComment && !isDeclaration) { #region "Attributes" //Attributes if (tn.Value[i] != ' ') { if (tn.Value[i] == '>') { tn.Index = i + 1; break; } else if (tn.Value[i] == '/' && tn.Value[i + 1] == '>') { elementAtEnd = true; tn.Index += 2; break; } else if (IsValidTagChar(tn.Value[i])) { JProperty att = ParseAttribute(tn.NewIndex(i)); i = tn.Index - 1; if (att != null && node != null) { ((JObject)node).Add(att); attNames.Add(att.Name); } } } #endregion } else { #region "Comment" if (isComment) { //Comment if ((breakOff == 2 && tn.Value[i] == '-' && tn.Value[i + 1] == '-' && tn.Value[i + 2] == '>') || (breakOff == 0 && tn.Value[i] == '>') || (breakOff == 1 && tn.Value[i] == '-' && tn.Value[i + 1] == '>')) { //if (parent != null) parent.Add(new XComment(comment)); tn.Index = i + breakOff + 1; break; } else { comment += tn.Value[i]; }/**/ } #endregion #region"Declaration" else if (isDeclaration) { //Declaration if (tn.Value[i] == '?' && tn.Value[i + 1] == '>') { //if (parent != null && parent is XDocument) this.SetDeclaration(declVer, declEnc, declSta, (XDocument)parent); tn.Index = i + 2; break; } else if (IsValidTagChar(tn.Value[i])) { JProperty att = ParseAttribute(tn.NewIndex(i)); i = tn.Index - 1; /* if (att != null) { if (att.Name.ToLower() == "version") { declVer = att.Value; } else if (att.Name.ToLower() == "encoding") { declEnc = att.Value; } else if (att.Name.ToLower() == "standalone") { declSta = att.Value; } }*/ } } #endregion } } #endregion if (name == "link") { elementAtEnd = true; } ///Add to parent if (node != null && parent != null) { this.AddItemToParent(node, name, parent); } if (node != null && elementAtEnd == false) { #region "Content & End Tag" //Content & End Tag string innerText = string.Empty; for (int i = tn.Index; i < tn.Value.Length; i++) { if (tn.Value[i] == '<') { if (tn.Value[i + 1] == '/') { #region "InnerText" //InnerText --> JValue if (innerText.Trim(new char[] { ' ', '\n', '\r', '\t' }).IsNullOrWhiteSpace() == false) { if (((JObject)node).Count == 0) { var newValue = new JValue(this.DecodeXml(innerText)); foreach (JProperty elem in parent.Children<JProperty>()) { if (elem.Name == name) { if (elem.Value is JObject) { elem.Value = newValue; } else if (elem.Value is JArray) { var arr = (JArray)elem.Value; int index = arr.IndexOf(node); if (index >= 0) { arr.Insert(index, newValue); arr.RemoveAt(index + 1); } } } } node = newValue; } else { if (node[CONTENT_PROPERTY_NAME] == null) { ((JObject)node).Add(new JProperty(CONTENT_PROPERTY_NAME, DecodeXml(innerText))); } else { ((JValue)node[CONTENT_PROPERTY_NAME]).Value = ((JValue)node[CONTENT_PROPERTY_NAME]).Value.ToString() + "\n" + DecodeXml(innerText); } } innerText = string.Empty; } #endregion #region "End Tag" //End Tag string endName = ParseName(tn.NewIndex(i + 2)); if (endName != null) { if (endName == name) { //Correct actual end name tn.Index = i + 3 + name.Length; break; } else { //Other end name JObject pare = this.FindParent(node, endName); if (pare != null) { //Other end name relies to one parent --> move all, except attributes, to direct parent. if (node is JObject) { this.MoveAllChildElementsToParent((JObject)node, parent, attNames); } tn.Index = i; break; } else { //Unknown end name --> ignore tn.Index = i + endName.ToString().Length + 2; i = tn.Index - 1; } } } else { throw new Exception("Invalid End Name."); } #endregion } else { //Child Start Tag var child = this.ParseNode(tn.NewIndex(i), (JObject)node); if (child.Key == "br") { innerText += "\n"; } else if (child.Key != "a" && child.Key != "small") { if (innerText.IsNullOrWhiteSpace() == false) { JObject p = new JObject(); p.Add(new JProperty(CONTENT_PROPERTY_NAME, innerText)); innerText = string.Empty; this.AddItemToParent(p, "p", (JObject)node); } } i = tn.Index - 1; } } else if (!(tn.Value[i] == ' ' && innerText == string.Empty)) { //Inner Text innerText += tn.Value[i]; } } #endregion } } tn.TrimStart(); return new KeyValuePair<string, JToken>(name, node); }