/// <summary> /// Deep copy of the path entries, so changes made to the entries of /// the original or cloned paths do not affect the other path. /// </summary> /// <returns></returns> public XmlParserPath Clone() { XmlParserPath clone = new XmlParserPath(); foreach (var pathEntry in _path) { clone.Append(pathEntry.Clone()); } return(clone); }
/// <summary> /// Updates the current state after a successful move. /// </summary> /// <returns>Return whether the parser is still in valid state (true) or not (false).</returns> bool UpdateState(IXmlTagParsingStrategy parsingStrategy) { // Find the end of the current tag. if (!parsingStrategy.FindEndOfTag(_xml, _cursor)) { // Tag is not closed. return(Invalidate()); } // Fit cursor to exact tag boundaries. while (_cursor.EndPosition > _cursor.StartPosition && _xml[_cursor.EndPosition - 1] != '>') { _cursor.EndPosition--; } if (_cursor.EndPosition <= _cursor.StartPosition) { return(Invalidate()); } XmlParserTagInfo currentTag = Current; if (currentTag != XmlParserTagInfo.NullTag && !(currentTag.IsEmptyElement || currentTag.IsElementClosingTag)) { _path.Append(currentTag); } bool isElementClosingTag = false; bool isEmptyElement = false; // Determine whether the current tag is an element closing tag. if (IsClosingTag(Cursor.StartPosition)) { isElementClosingTag = true; } else { // Determine whether the current element is empty (no children). if (_xml[Cursor.EndPosition - 2] == '/') { isEmptyElement = true; } } string currentTagName; if (!GetTagName(Cursor.StartPosition, out currentTagName)) { return(Invalidate()); } currentTag = new XmlParserTagInfo(_cursor, currentTagName); currentTag.IsEmptyElement = isEmptyElement; currentTag.IsElementClosingTag = isElementClosingTag; Current = currentTag; if (isElementClosingTag) { XmlParserTagInfo tag = _path.RemoveLastEntry(); Debug.Assert(tag.Name == currentTagName, "Popped tag name '" + tag.Name + "' is not as expected: '" + currentTagName + "'"); Current.IsBoundaryElement = tag.IsBoundaryElement; } return(true); }