Exemplo n.º 1
0
 public void CopyAttributes(Node n)
 {
     for(int i = 0, len = n.attributes.Count; i < len; i++) {
         var a = (Attribute) n.attributes[i];
         var na = this.AddAttribute(a.Name, a.Value, a.QuoteChar, false);
         na.DtdType = a.DtdType;
     }
 }
Exemplo n.º 2
0
        /// <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(m_current == null) {
                OpenInput();
            }

            var start = this.m_state;
            if(m_node.Simulated) {
                // return the next node
                m_node.Simulated = false;
                this.m_node = Top();
                this.m_state = this.m_node.CurrentState;
                return true;
            }

            var foundnode = false;
            while(!foundnode) {
                switch(this.m_state) {
                    case State.Initial:
                        this.m_state = State.Markup;
                        this.m_current.ReadChar();
                        goto case State.Markup;
                    case State.Eof:
                        if(this.m_current.Parent != null) {
                            this.m_current.Close();
                            this.m_current = this.m_current.Parent;
                        }
                        else {
                            return false;
                        }
                        break;
                    case State.EndTag:
                        if(string.Equals(this.m_endTag, this.m_node.Name, StringComparison.OrdinalIgnoreCase)) {
                            Pop(); // we're done!
                            this.m_state = State.Markup;
                            goto case State.Markup;
                        }
                        Pop(); // close one element
                        foundnode = true; // return another end element.
                        break;
                    case State.Markup:
                        if(this.m_node.IsEmpty) {
                            Pop();
                        }
                        var n = this.m_node;
                        foundnode = ParseMarkup();
                        break;
                    case State.PartialTag:
                        Pop(); // remove text node.
                        this.m_state = State.Markup;
                        foundnode = ParseTag(this.m_partial);
                        break;
                    case State.PseudoStartTag:
                        foundnode = ParseStartTag('<');
                        break;
                    case State.AutoClose:
                        Pop(); // close next node.
                        if(this.m_stack.Count <= this.m_poptodepth) {
                            this.m_state = State.Markup;
                            if(this.m_newnode != null) {
                                Push(this.m_newnode); // now we're ready to start the new node.
                                this.m_newnode = null;
                                this.m_state = State.Markup;
                            }
                            else if(this.m_node.NodeType == XmlNodeType.Document) {
                                this.m_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.m_state = State.Markup;
                        goto case State.Markup;
                    case State.Text:
                        Pop();
                        goto case State.Markup;
                    case State.PartialText:
                        if(ParseText(this.m_current.Lastchar, false)) {
                            this.m_node.NodeType = XmlNodeType.Whitespace;
                        }

                        foundnode = true;
                        break;
                }

                if(foundnode && this.m_node.NodeType == XmlNodeType.Whitespace && this.m_whitespaceHandling == WhitespaceHandling.None) {
                    // strip out whitespace (caller is probably pretty printing the XML).
                    foundnode = false;
                }
                if(!foundnode && this.m_state == State.Eof && this.m_stack.Count > 1) {
                    this.m_poptodepth = 1;
                    this.m_state = State.AutoClose;
                    this.m_node = Top();
                    return true;
                }
            }
            if(!m_foundRoot && (this.NodeType == XmlNodeType.Element ||
                                this.NodeType == XmlNodeType.Text ||
                                this.NodeType == XmlNodeType.CDATA)) {
                m_foundRoot = true;
                if(this.IsHtml && (this.NodeType != XmlNodeType.Element ||
                                   !string.Equals(this.LocalName, "html", StringComparison.OrdinalIgnoreCase))) {
                    // Simulate an HTML root element!
                    this.m_node.CurrentState = this.m_state;
                    var root = Push("html", XmlNodeType.Element, null);
                    SwapTopNodes(); // make html the outer element.
                    this.m_node = root;
                    root.Simulated = true;
                    root.IsEmpty = false;
                    this.m_state = State.Markup;
                    //this.state = State.PseudoStartTag;
                    //this.startTag = name;
                }

                return true;
            }

            return true;
        }
Exemplo n.º 3
0
        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.
                var name = node.Name.ToUpperInvariant(); // DTD is in upper case
                var i = 0;
                var 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--) {
                        var n = (Node) this.m_stack[i];
                        if(n.IsEmpty) {
                            continue; // we'll have to pop this one
                        }
                        var 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) {
                    var 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
                        var closing = "";
                        for(var k = top; k >= i + 1; k--) {
                            if(closing != "") {
                                closing += ",";
                            }
                            var 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;
                }
            }
        }
Exemplo n.º 4
0
 private void Validate(Node node)
 {
     if(this.m_dtd != null) {
         var e = this.m_dtd.FindElement(node.Name);
         if(e != null) {
             node.DtdType = e;
             if(e.ContentModel.DeclaredContent == DeclaredContent.EMPTY) {
                 node.IsEmpty = true;
             }
         }
     }
 }
Exemplo n.º 5
0
 private Node Push(Node n)
 {
     // we have to do a deep clone of the Node object because
     // it is reused in the stack.
     var 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.m_node = n2;
     return n2;
 }
Exemplo n.º 6
0
        private Node Push(string name, XmlNodeType nt, string value)
        {
            var result = (Node) this.m_stack.Push();
            if(result == null) {
                result = new Node();
                this.m_stack[this.m_stack.Count - 1] = result;
            }

            result.Reset(name, nt, value);
            this.m_node = result;
            return result;
        }
Exemplo n.º 7
0
 private void Pop()
 {
     if(this.m_stack.Count > 1) {
         this.m_node = (Node) this.m_stack.Pop();
     }
 }
Exemplo n.º 8
0
        private bool ParseEndTag()
        {
            this.m_state = State.EndTag;
            this.m_current.ReadChar(); // consume '/' char.
            var name = this.ScanName(tagterm);
            var 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.
            var caseInsensitive = (this.m_folding == CaseFolding.None);
            this.m_node = (Node) this.m_stack[this.m_stack.Count - 1];
            for(var i = this.m_stack.Count - 1; i > 0; i--) {
                var 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;
        }
Exemplo n.º 9
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();
 }
Exemplo n.º 10
0
 private static void ValidateAttribute(Node node, Attribute a)
 {
     var e = node.DtdType;
     if(e != null) {
         var ad = e.FindAttribute(a.Name);
         if(ad != null) {
             a.DtdType = ad;
         }
     }
 }