/// <summary> /// Inserts the specified attribute as the last attribute in the collection. /// </summary> /// <param name="newAttribute">The attribute to insert. May not be null.</param> /// <returns>The appended attribute.</returns> public HtmlAttribute Append(HtmlAttribute newAttribute) { if (newAttribute == null) { throw new ArgumentNullException("newAttribute"); } _hashitems[newAttribute.Name] = newAttribute; newAttribute._ownernode = _ownernode; _items.Add(newAttribute); _ownernode._innerchanged = true; _ownernode._outerchanged = true; return newAttribute; }
/// <summary> /// Creates a duplicate of this attribute. /// </summary> /// <returns>The cloned attribute.</returns> public HtmlAttribute Clone() { HtmlAttribute att = new HtmlAttribute(_ownerdocument); att.Name = Name; att.Value = Value; return att; }
internal int GetAttributeIndex(HtmlAttribute attribute) { if (attribute == null) { throw new ArgumentNullException("attribute"); } for (int i = 0; i < _items.Count; i++) { if (((HtmlAttribute)_items[i]) == attribute) return i; } return -1; }
/// <summary> /// Removes a given attribute from the list. /// </summary> /// <param name="attribute">The attribute to remove. May not be null.</param> public void Remove(HtmlAttribute attribute) { if (attribute == null) { throw new ArgumentNullException("attribute"); } int index = GetAttributeIndex(attribute); if (index == -1) { throw new IndexOutOfRangeException(); } RemoveAt(index); }
private void PushAttributeNameStart(int index) { _currentattribute = CreateAttribute(); _currentattribute._namestartindex = index; _currentattribute._line = _line; _currentattribute._lineposition = _lineposition; _currentattribute._streamposition = index; }
private void Parse() { int lastquote = 0; _lastnodes = new Hashtable(); _c = 0; _fullcomment = false; _parseerrors = new ArrayList(); _line = 1; _lineposition = 1; _maxlineposition = 1; _state = ParseState.Text; _oldstate = _state; _documentnode._innerlength = _text.Length; _documentnode._outerlength = _text.Length; _remainderOffset = _text.Length; _lastparentnode = _documentnode; _currentnode = CreateNode(HtmlNodeType.Text, 0); _currentattribute = null; _index = 0; PushNodeStart(HtmlNodeType.Text, 0); while (_index<_text.Length) { _c = _text[_index]; IncrementPosition(); switch(_state) { case ParseState.Text: if (NewCheck()) continue; break; case ParseState.WhichTag: if (NewCheck()) continue; if (_c == '/') { PushNodeNameStart(false, _index); } else { PushNodeNameStart(true, _index-1); DecrementPosition(); } _state = ParseState.Tag; break; case ParseState.Tag: if (NewCheck()) continue; if (IsWhiteSpace(_c)) { PushNodeNameEnd(_index-1); if (_state != ParseState.Tag) continue; _state = ParseState.BetweenAttributes; continue; } if (_c == '/') { PushNodeNameEnd(_index-1); if (_state != ParseState.Tag) continue; _state = ParseState.EmptyTag; continue; } if (_c == '>') { PushNodeNameEnd(_index-1); if (_state != ParseState.Tag) continue; if (!PushNodeEnd(_index, false)) { // stop parsing _index = _text.Length; break; } if (_state != ParseState.Tag) continue; _state = ParseState.Text; PushNodeStart(HtmlNodeType.Text, _index); } break; case ParseState.BetweenAttributes: if (NewCheck()) continue; if (IsWhiteSpace(_c)) continue; if ((_c == '/') || (_c == '?')) { _state = ParseState.EmptyTag; continue; } if (_c == '>') { if (!PushNodeEnd(_index, false)) { // stop parsing _index = _text.Length; break; } if (_state != ParseState.BetweenAttributes) continue; _state = ParseState.Text; PushNodeStart(HtmlNodeType.Text, _index); continue; } PushAttributeNameStart(_index-1); _state = ParseState.AttributeName; break; case ParseState.EmptyTag: if (NewCheck()) continue; if (_c == '>') { if (!PushNodeEnd(_index, true)) { // stop parsing _index = _text.Length; break; } if (_state != ParseState.EmptyTag) continue; _state = ParseState.Text; PushNodeStart(HtmlNodeType.Text, _index); continue; } _state = ParseState.BetweenAttributes; break; case ParseState.AttributeName: if (NewCheck()) continue; if (IsWhiteSpace(_c)) { PushAttributeNameEnd(_index-1); _state = ParseState.AttributeBeforeEquals; continue; } if (_c == '=') { PushAttributeNameEnd(_index-1); _state = ParseState.AttributeAfterEquals; continue; } if (_c == '>') { PushAttributeNameEnd(_index-1); if (!PushNodeEnd(_index, false)) { // stop parsing _index = _text.Length; break; } if (_state != ParseState.AttributeName) continue; _state = ParseState.Text; PushNodeStart(HtmlNodeType.Text, _index); continue; } break; case ParseState.AttributeBeforeEquals: if (NewCheck()) continue; if (IsWhiteSpace(_c)) continue; if (_c == '>') { if (!PushNodeEnd(_index, false)) { // stop parsing _index = _text.Length; break; } if (_state != ParseState.AttributeBeforeEquals) continue; _state = ParseState.Text; PushNodeStart(HtmlNodeType.Text, _index); continue; } if (_c == '=') { _state = ParseState.AttributeAfterEquals; continue; } // no equals, no whitespace, it's a new attrribute starting _state = ParseState.BetweenAttributes; DecrementPosition(); break; case ParseState.AttributeAfterEquals: if (NewCheck()) continue; if (IsWhiteSpace(_c)) continue; if ((_c == '\'') || (_c == '"')) { _state = ParseState.QuotedAttributeValue; PushAttributeValueStart(_index); lastquote = _c; continue; } if (_c == '>') { if (!PushNodeEnd(_index, false)) { // stop parsing _index = _text.Length; break; } if (_state != ParseState.AttributeAfterEquals) continue; _state = ParseState.Text; PushNodeStart(HtmlNodeType.Text, _index); continue; } PushAttributeValueStart(_index-1); _state = ParseState.AttributeValue; break; case ParseState.AttributeValue: if (NewCheck()) continue; if (IsWhiteSpace(_c)) { PushAttributeValueEnd(_index-1); _state = ParseState.BetweenAttributes; continue; } if (_c == '>') { PushAttributeValueEnd(_index-1); if (!PushNodeEnd(_index, false)) { // stop parsing _index = _text.Length; break; } if (_state != ParseState.AttributeValue) continue; _state = ParseState.Text; PushNodeStart(HtmlNodeType.Text, _index); continue; } break; case ParseState.QuotedAttributeValue: if (_c == lastquote) { PushAttributeValueEnd(_index-1); _state = ParseState.BetweenAttributes; continue; } if (_c == '<') { if (_index<_text.Length) { if (_text[_index] == '%') { _oldstate = _state; _state = ParseState.ServerSideCode; continue; } } } break; case ParseState.Comment: if (_c == '>') { if (_fullcomment) { if ((_text[_index-2] != '-') || (_text[_index-3] != '-')) { continue; } } if (!PushNodeEnd(_index, false)) { // stop parsing _index = _text.Length; break; } _state = ParseState.Text; PushNodeStart(HtmlNodeType.Text, _index); continue; } break; case ParseState.ServerSideCode: if (_c == '%') { if (_index<_text.Length) { if (_text[_index] == '>') { switch(_oldstate) { case ParseState.AttributeAfterEquals: _state = ParseState.AttributeValue; break; case ParseState.BetweenAttributes: PushAttributeNameEnd(_index+1); _state = ParseState.BetweenAttributes; break; default: _state = _oldstate; break; } IncrementPosition(); } } } break; case ParseState.PcData: // look for </tag + 1 char // check buffer end if ((_currentnode._namelength+3)<=(_text.Length-(_index-1))) { if (string.Compare(_text.Substring(_index-1, _currentnode._namelength+2), "</" + _currentnode.Name, true) == 0) { int c = _text[_index-1 + 2 + _currentnode.Name.Length]; if ((c == '>') || (IsWhiteSpace(c))) { // add the script as a text node HtmlNode script = CreateNode(HtmlNodeType.Text, _currentnode._outerstartindex + _currentnode._outerlength); script._outerlength = _index-1 - script._outerstartindex; _currentnode.AppendChild(script); PushNodeStart(HtmlNodeType.Element, _index-1); PushNodeNameStart(false, _index-1 +2); _state = ParseState.Tag; IncrementPosition(); } } } break; } } // finish the current work if (_currentnode._namestartindex > 0) { PushNodeNameEnd(_index); } PushNodeEnd(_index, false); // we don't need this anymore _lastnodes.Clear(); }