public void CopyAttributes(SgmlNode node) { Precondition.Require(node, () => Error.ArgumentNull("node")); int index = 0; int count = node._attributes.Count; while (index < count) { Attribute attribute = node._attributes[index]; AddAttribute(attribute.Name, attribute.Value, attribute.QuoteChar, false).DtdType = attribute.DtdType; index++; } }
/// <summary> /// Reads the next node from the stream. /// </summary> /// <returns>true if the next node was read successfully; /// false if there are no more nodes to read.</returns> public override bool Read() { if (_current == null) OpenInput(); if (_node.Simulated) { _node.Simulated = false; _node = Top(); _state = _node.State; return true; } bool foundNode = false; while (!foundNode) { switch (_state) { case State.Initial: _state = State.Markup; _current.ReadChar(); goto case State.Markup; case State.Eof: if (_current.Parent != null) { _current.Close(); _current = _current.Parent; } else return false; break; case State.EndTag: if (String.Equals(_endTag, _node.Name, StringComparison.InvariantCultureIgnoreCase)) { Pop(); _state = State.Markup; goto case State.Markup; } Pop(); foundNode = true; break; case State.Markup: if (_node.IsEmpty) Pop(); foundNode = ParseMarkup(); break; case State.PartialTag: Pop(); _state = State.Markup; foundNode = ParseTag(_partial); break; case State.PseudoStartTag: foundNode = ParseStartTag('<'); break; case State.AutoClose: Pop(); if (_stack.Count <= _popToDepth) { _state = State.Markup; if (_newNode != null) { Push(_newNode); _newNode = null; _state = State.Markup; } else if (_node.NodeType == XmlNodeType.Document) { _state = State.Eof; goto case State.Eof; } } foundNode = true; break; case State.CData: foundNode = ParseCData(); break; case State.Attr: goto case State.AttrValue; case State.AttrValue: _state = State.Markup; goto case State.Markup; case State.Text: Pop(); goto case State.Markup; case State.PartialText: if (ParseText(_current.LastChar, false)) _node.NodeType = XmlNodeType.Whitespace; foundNode = true; break; } if (foundNode && _node.NodeType == XmlNodeType.Whitespace && _whitespaceHandling == WhitespaceHandling.None) foundNode = false; if (!foundNode && _state == State.Eof && _stack.Count > 1) { _popToDepth = 1; _state = State.AutoClose; _node = Top(); return true; } } if (!_foundRoot && (NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Text || NodeType == XmlNodeType.CDATA)) { _foundRoot = true; if (IsHtml && (NodeType != XmlNodeType.Element || !String.Equals(LocalName, "html", StringComparison.InvariantCultureIgnoreCase))) { _node.State = _state; SgmlNode root = Push("html", XmlNodeType.Element, null); SwapTopNodes(); _node = root; root.Simulated = true; root.IsEmpty = false; _state = State.Markup; } return true; } return true; }
private static void ValidateAttribute(SgmlNode node, Attribute a) { ElementDeclaration e = node.DtdType; if (e != null) { AttributeDefinition ad = e.FindAttribute(a.Name); if (ad != null) a.DtdType = ad; } }
private void ValidateContent(SgmlNode node) { if (node.NodeType == XmlNodeType.Element) { if (!VerifyName(node.Name)) { Pop(); Push(null, XmlNodeType.Text, "<" + node.Name + ">"); return; } } if (_dtd != null) { string name = node.Name.ToUpper(CultureInfo.InvariantCulture); int i = 0; int top = _stack.Count - 2; if (node.DtdType != null) { for (i = top; i > 0; i--) { SgmlNode n = _stack[i]; if (n.IsEmpty) continue; ElementDeclaration f = n.DtdType; if (f != null) { if (i == 2 && String.Equals(f.Name, "BODY", StringComparison.InvariantCultureIgnoreCase)) break; else if (String.Equals(f.Name, _dtd.Name, StringComparison.InvariantCultureIgnoreCase)) break; else if (f.CanContain(name, _dtd)) break; else if (!f.EndTagOptional) break; } else break; } } if (i == 0) { return; } else if (i < top) { SgmlNode n = _stack[top]; if (i == top - 1 && String.Equals(name, n.Name, StringComparison.InvariantCultureIgnoreCase)) { // e.g. p not allowed inside p, not an interesting error. } else { #if DEBUG string closing = ""; for (int k = top; k >= i+1; k--) { if (closing != "") closing += ","; SgmlNode n2 = _stack[k]; closing += "<" + n2.Name + ">"; } Log("Element '{0}' not allowed inside '{1}', closing {2}.", name, n.Name, closing); #endif } _state = State.AutoClose; _newNode = node; Pop(); _popToDepth = i + 1; } } }
private void Validate(SgmlNode node) { if (_dtd != null) { ElementDeclaration e = _dtd.FindElement(node.Name); if (e != null) { node.DtdType = e; if (e.ContentModel.DeclaredContent == DeclaredContent.Empty) node.IsEmpty = true; } } }
private bool ParseEndTag() { _state = State.EndTag; _current.ReadChar(); string name = ScanName(_tagTerm); char ch = _current.SkipWhitespace(); if (ch != '>') { Log("Expected empty start tag '/>' sequence instead of '{0}'", ch); _current.ScanToEnd(_builder, "Recovering", ">"); } _current.ReadChar(); _endTag = name; bool caseInsensitive = (_folding == CaseFolding.None); _node = _stack[_stack.Count - 1]; for (int i = _stack.Count - 1; i > 0; i--) { SgmlNode n = _stack[i]; if (String.Compare(n.Name, name, caseInsensitive, CultureInfo.InvariantCulture) == 0) { _endTag = n.Name; return true; } } Log("No matching start tag for '</{0}>'", name); _state = State.Markup; return false; }
private void Pop() { if (_stack.Count > 1) _node = _stack.Pop(); }
private SgmlNode Push(SgmlNode n) { SgmlNode n2 = Push(n.Name, n.NodeType, n.Value); n2.DtdType = n.DtdType; n2.IsEmpty = n.IsEmpty; n2.Space = n.Space; n2.XmlLang = n.XmlLang; n2.State = n.State; n2.CopyAttributes(n); _node = n2; return n2; }
private SgmlNode Push(string name, XmlNodeType nodeType, string value) { SgmlNode result = _stack.Push(); if (result == null) { result = new SgmlNode(); _stack[_stack.Count - 1] = result; } result.Reset(name, nodeType, value); _node = result; return result; }
protected virtual void Init() { _state = State.Initial; _stack = new HWStack<SgmlNode>(10); _node = Push(null, XmlNodeType.Document, null); _node.IsEmpty = false; _builder = new StringBuilder(); _nameBuilder = new StringBuilder(); _popToDepth = 0; _current = null; _partial = '\0'; _endTag = null; _attr = null; _attrPosition = 0; _newNode = null; _rootCount = 0; _foundRoot = false; _unknownNamespaces.Clear(); }