void Init() { this.state = State.Initial; this.stack = new HWStack(10); this.node = Push(null, XmlNodeType.Document, null); this.node.IsEmpty = false; this.sb = new StringBuilder(); this.name = new StringBuilder(); this.poptodepth = 0; this.current = null; this.partial = '\0'; this.endTag = null; this.a = null; this.apos = 0; this.newnode = null; this.rootCount = 0; this.foundRoot = false; }
void ValidateContent(Node node) { if (this.dtd != null) { // See if this element is allowed inside the current element. // If it isn't, then auto-close elements until we find one // that it is allowed to be in. string name = this.nametable.Add(node.Name.ToUpper()); // DTD is in upper case int i = 0; int top = this.stack.Count-2; if (node.DtdType != null) { // it is a known element, let's see if it's allowed in the // current context. for (i = top; i>0; i--) { Node n = (Node)this.stack[i]; if (n.IsEmpty) continue; // we'll have to pop this one ElementDecl f = n.DtdType; if (f != null) { if (f.Name == this.dtd.Name) break; // can't pop the root element. if (f.CanContain(name, this.dtd)) { break; } else if (!f.EndTagOptional) { // If the end tag is not optional then we can't // auto-close it. We'll just have to live with the // junk we've found and move on. break; } } else { // Since we don't understand this tag anyway, // we might as well allow this content! break; } } } if (i == 0) { // Tag was not found or is not allowed anywhere, ignore it and // continue on. } else if (i < top) { Node n = (Node)this.stack[top]; if (i == top - 1 && name == n.Name) { // e.g. p not allowed inside p, not an interesting error. } else { string closing = ""; for (int k = top; k >= i+1; k--) { if (closing != "") closing += ","; Node n2 = (Node)this.stack[k]; closing += "<"+n2.Name+">"; } Log("Element '{0}' not allowed inside '{1}', closing {2}.", name, n.Name, closing); } this.state = State.AutoClose; this.newnode = node; Pop(); // save this new node until we pop the others this.poptodepth = i+1; } } }
public void CopyAttributes(Node n) { for (int i = 0, len = n.attributes.Count; i < len; i++) { Attribute a = (Attribute)n.attributes[i]; Attribute na = this.AddAttribute(a.Name, a.Value, a.QuoteChar, false); na.DtdType = a.DtdType; } }
void Validate(Node node) { if (this.dtd != null) { ElementDecl e = this.dtd.FindElement(node.Name); if (e != null) { node.DtdType = e; if (e.ContentModel.DeclaredContent == DeclaredContent.EMPTY) node.IsEmpty = true; } } }
void ValidateAttribute(Node node, Attribute a) { ElementDecl e = node.DtdType; if (e != null) { AttDef ad = e.FindAttribute(a.Name); if (ad != null) { a.DtdType = ad; } } }
void Pop() { if (this.stack.Count > 1) { this.node = (Node)this.stack.Pop(); } }
void Pop() { if (_depth > 1) { _depth--; _node = _stack[_depth-1]; } }
private bool ParseEndTag() { this.m_state = State.EndTag; this.m_current.ReadChar(); // consume '/' char. string name = this.ScanName(SgmlReader.tagterm); char ch = this.m_current.SkipWhitespace(); if (ch != '>') { Log("Expected empty start tag '/>' sequence instead of '{0}'", ch); this.m_current.ScanToEnd(null, "Recovering", ">"); } this.m_current.ReadChar(); // consume '>' this.m_endTag = name; // Make sure there's a matching start tag for it. bool caseInsensitive = (this.m_folding == CaseFolding.None); this.m_node = (Node)this.m_stack[this.m_stack.Count - 1]; for (int i = this.m_stack.Count - 1; i > 0; i--) { Node n = (Node)this.m_stack[i]; if (string.Equals(n.Name, name, caseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) { this.m_endTag = n.Name; return true; } } Log("No matching start tag for '</{0}>'", name); this.m_state = State.Markup; return false; }
private void Pop() { if (this.m_stack.Count > 1) { this.m_node = (Node)this.m_stack.Pop(); } }
void Init() { _state = State.Initial; _stack = new Node[10]; _size = 10; _depth = 0; _node = Push(null, XmlNodeType.Document, null); _node.IsEmpty = false; _sb = new StringBuilder(); _name = new StringBuilder(); _poptodepth = 0; _current = null; _partial = '\0'; _endTag = null; _a = null; _apos = 0; _newnode = null; _poptodepth = 0; _rootCount = 0; }
private void Init() { this.m_state = State.Initial; this.m_stack = new HWStack(10); this.m_node = Push(null, XmlNodeType.Document, null); this.m_node.IsEmpty = false; this.m_sb = new StringBuilder(); this.m_name = new StringBuilder(); this.m_poptodepth = 0; this.m_current = null; this.m_partial = '\0'; this.m_endTag = null; this.m_a = null; this.m_apos = 0; this.m_newnode = null; this.m_rootCount = 0; this.m_foundRoot = false; this.unknownNamespaces.Clear(); }
void Grow() { int inc = 10; int newsize = _size+inc; Node[] narray = new Node[newsize]; Array.Copy(_stack, narray, _size); _size = newsize; _stack = narray; }
public void CopyAttributes(Node n) { for (int i = 0; i < n._attcount; i++) { Attribute a = n._attributes[i]; Attribute na = this.AddAttribute(a.Name, a.Value, a.QuoteChar); na.DtdType = a.DtdType; } }
Node Push(string name, XmlNodeType nt, string value) { if (_depth == _size) Grow(); Node result; if (_stack[_depth] == null) { result = new Node(name, nt, value); _stack[_depth] = result; } else { result = _stack[_depth]; result.Reset(name, nt, value); } _depth++; _node = result; return result; }
Node Push(string name, XmlNodeType nt, string value) { Node result = (Node)this.stack.Push(); if (result == null) { result = new Node(); this.stack[this.stack.Count-1] = result; } result.Reset(name, nt, value); this.node = result; return result; }
private void ValidateContent(Node node) { if (node.NodeType == XmlNodeType.Element) { if (!VerifyName(node.Name)) { Pop(); Push(null, XmlNodeType.Text, "<" + node.Name + ">"); return; } } if (this.m_dtd != null) { // See if this element is allowed inside the current element. // If it isn't, then auto-close elements until we find one // that it is allowed to be in. string name = node.Name.ToUpperInvariant(); // DTD is in upper case int i = 0; int top = this.m_stack.Count - 2; if (node.DtdType != null) { // it is a known element, let's see if it's allowed in the // current context. for (i = top; i > 0; i--) { Node n = (Node)this.m_stack[i]; if (n.IsEmpty) continue; // we'll have to pop this one ElementDecl f = n.DtdType; if (f != null) { if ((i == 2) && string.Equals(f.Name, "BODY", StringComparison.OrdinalIgnoreCase)) // NOTE (steveb): never close the BODY tag too early break; else if (string.Equals(f.Name, this.m_dtd.Name, StringComparison.OrdinalIgnoreCase)) break; // can't pop the root element. else if (f.CanContain(name, this.m_dtd)) { break; } else if (!f.EndTagOptional) { // If the end tag is not optional then we can't // auto-close it. We'll just have to live with the // junk we've found and move on. break; } } else { // Since we don't understand this tag anyway, // we might as well allow this content! break; } } } if (i == 0) { // Tag was not found or is not allowed anywhere, ignore it and // continue on. return; } else if (i < top) { Node n = (Node)this.m_stack[top]; if (i == top - 1 && string.Equals(name, n.Name, StringComparison.OrdinalIgnoreCase)) { // 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 += ","; Node n2 = (Node)this.m_stack[k]; closing += "<" + n2.Name + ">"; } Log("Element '{0}' not allowed inside '{1}', closing {2}.", name, n.Name, closing); #endif } this.m_state = State.AutoClose; this.m_newnode = node; Pop(); // save this new node until we pop the others this.m_poptodepth = i + 1; } } }
Node Push(Node n) { // we have to do a deep clone of the Node object because // it is reused in the stack. Node 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.CurrentState = n.CurrentState; n2.CopyAttributes(n); this.node = n2; return n2; }
bool ParseEndTag() { this.state = State.EndTag; this.current.ReadChar(); // consume '/' char. string name = this.ScanName(SgmlReader.tagterm); char ch = this.current.SkipWhitespace(); if (ch != '>') { Log("Expected empty start tag '/>' sequence instead of '{0}'", ch); this.current.ScanToEnd(null, "Recovering", ">"); } this.current.ReadChar(); // consume '>' this.endTag = name; // Make sure there's a matching start tag for it. bool caseInsensitive = (this.folding == CaseFolding.None); this.node = (Node)this.stack[this.stack.Count-1]; for (int i = this.stack.Count-1; i>0; i--) { Node n = (Node)this.stack[i]; if (caseInsensitive && string.Compare(n.Name, name, true) == 0) { this.endTag = n.Name; return true; } else if ((object)n.Name == (object)name) { return true; } } Log("No matching start tag for '</{0}>'", name); this.state = State.Markup; return false; }
public override bool Read() { if (current == null) { OpenInput(); } State start = this.state; if (node.Simulated) { // return the next node node.Simulated = false; this.node = Top(); this.state = this.node.CurrentState; return true; } bool foundnode = false; while (! foundnode) { switch (this.state) { case State.Initial: this.state = State.Markup; this.current.ReadChar(); goto case State.Markup; case State.Eof: if (this.current.Parent != null) { this.current.Close(); this.current = this.current.Parent; } else { return false; } break; case State.EndTag: if (this.endTag == (object)this.node.Name) { Pop(); // we're done! this.state = State.Markup; goto case State.Markup; } Pop(); // close one element foundnode = true;// return another end element. break; case State.Markup: if (this.node.IsEmpty) { Pop(); } Node n = this.node; foundnode = ParseMarkup(); break; case State.PartialTag: Pop(); // remove text node. this.state = State.Markup; foundnode = ParseTag(this.partial); break; case State.PseudoStartTag: foundnode = ParseStartTag('<'); break; case State.AutoClose: Pop(); // close next node. if (this.stack.Count <= this.poptodepth) { this.state = State.Markup; if (this.newnode != null) { Push(this.newnode); // now we're ready to start the new node. this.newnode = null; this.state = State.Markup; } else if (this.node.NodeType == XmlNodeType.Document) { this.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: this.state = State.Markup; goto case State.Markup; case State.Text: Pop(); goto case State.Markup; case State.PartialText: if (ParseText(this.current.Lastchar, false)) { this.node.NodeType = XmlNodeType.Whitespace; } foundnode = true; break; } if (foundnode && this.node.NodeType == XmlNodeType.Whitespace && this.whitespaceHandling == WhitespaceHandling.None) { // strip out whitespace (caller is probably pretty printing the XML). foundnode = false; } if (!foundnode && this.state == State.Eof && this.stack.Count>1) { this.poptodepth = 1; state = State.AutoClose; this.node = Top(); return true; } } if (!foundRoot && (this.NodeType == XmlNodeType.Element || this.NodeType == XmlNodeType.Text || this.NodeType == XmlNodeType.CDATA)) { foundRoot = true; if (this.IsHtml && (this.NodeType != XmlNodeType.Element || string.Compare(this.LocalName, "html", StringComparison.InvariantCultureIgnoreCase) != 0)) { // Simulate an HTML root element! this.node.CurrentState = this.state; Node root = Push("html", XmlNodeType.Element, null); SwapTopNodes(); // make html the outer element. this.node = root; root.Simulated = true; root.IsEmpty = false; this.state = State.Markup; //this.state = State.PseudoStartTag; //this.startTag = name; } return true; } return true; }
bool ParseEndTag() { _state = State.EndTag; _current.ReadChar(); // consume '/' char. string name = _current.ScanToken(_sb, _tagterm, false); char ch = _current.SkipWhitespace(); if (ch != '>') { Log("Expected empty start tag '/>' sequence instead of '{0}'", ch); _current.ScanToEnd(null, "Recovering", ">"); } _current.ReadChar(); // consume '>' // Make sure there's a matching start tag for it. _endTag = _nametable.Add(name.ToLower()); _node = _stack[_depth-1]; for (int i = _depth-1; i>0; i--) { if ((object)_stack[i].Name == _endTag) return true; } Log("No matching start tag for '</{0}>'", name); _state = State.Markup; return false; }