Exemple #1
0
 public XmlReader(IoMemory mem)
     : this()
 {
     if (mem == null)
     {
         throw new ArgumentNullException("mem");
     }
     stream = new KernelIoMemoryStream(mem);
 }
Exemple #2
0
 public XmlReader(byte[] buffer)
     : this()
 {
     if (buffer == null)
     {
         throw new ArgumentNullException("buffer");
     }
     stream = new KernelByteMemoryStream(buffer);
 }
Exemple #3
0
        //////////////////////////////////////////////////////////////////////
        //
        public XmlNode Parse()
        {
            if (stream == null)
            {
                return(doc);
            }

            TokenType type;
            string    token            = null;
            XmlNode   curNode          = null;
            string    curAttributeName = null;

            // Check for a UTF-8 preamble.
            isUtf8 = false;
            if (PeekCharacter() == 0xef)
            {
                if (ReadCharacter() == 0xef &&
                    ReadCharacter() == 0xbb &&
                    ReadCharacter() == 0xbf)
                {
                    isUtf8 = true;
                }
            }

            while (ReadToken(out token, out type))
            {
                switch (state)
                {
                case States.START:
                    if (type == TokenType.OPERATOR && token.Equals("<"))
                    {
                        state = States.NEED_ELEMENT_NAME;
                    }
                    else
                    {
                        // All other text is interpreted as freestanding text.
                        // It had better occur within a tag!
                        if (stackTop == 0)
                        {
                            throw new XmlException(lineNumber, "Line " + lineNumber + ": Text must be inside a tag");
                        }

                        XmlNode lastNode = Peek();
                        lastNode.AddText(token);

                        // Next state depends on whether we're at the end of
                        // the text-within-a-tag already or not.
                        if (PeekCharacter() == '<')
                        {
                            // Looks like we're already at the end
                            state = States.START;
                        }
                        else
                        {
                            state = States.GET_STRINGS;
                        }
                    }
                    break;

                case States.NEED_ELEMENT_NAME:
                    if (type == TokenType.NAME)
                    {
                        state   = States.NEED_ATTRIBUTE_NAME;
                        curNode = new XmlNode(token);
                    }
                    else if (type == TokenType.OPERATOR && token.Equals("/"))
                    {
                        state = States.NEED_CLOSURE_NAME;
                    }
                    else if (type == TokenType.OPERATOR &&
                             (token.Equals("?") ||
                              token.Equals("!") ||
                              token.Equals('-')))
                    {
                        // then go to the question mark state and ignore this element
                        state = States.QUESTION_MARK_ELEMENT;
                    }
                    else
                    {
                        throw new XmlException(lineNumber, "Line " + lineNumber + ": Can only begin a tag with / or a name");
                    }
                    break;

                case States.NEED_ATTRIBUTE_NAME:
                    if (type == TokenType.NAME)
                    {
                        state            = States.NEED_EQUALS_SIGN;
                        curAttributeName = token;
                    }
                    else if (type == TokenType.OPERATOR && token.Equals(">"))
                    {
                        // hold onto this node so we can check it later
                        state = States.START;

                        if (stackTop != 0)
                        {
                            XmlNode parent = Peek();
                            parent.AddChild(curNode);
                        }
                        else
                        {
                            doc.AddChild(curNode);
                        }
                        Push(curNode);
                        curNode = null;
                    }
                    else if (type == TokenType.OPERATOR && token.Equals("/"))
                    {
                        // this node is almost complete
                        state = States.NEED_CLOSURE_BRACKET;
                    }
                    else
                    {
                        throw new XmlException(lineNumber, "Line " + lineNumber + ": Must have either attributes, '/>', or '>' after the name of an element");
                    }
                    break;

                case States.NEED_EQUALS_SIGN:
                    if (type == TokenType.OPERATOR && token.Equals("="))
                    {
                        state = States.NEED_ATTRIBUTE_VALUE;
                    }
                    else
                    {
                        throw new XmlException(lineNumber, "Line " + lineNumber + ": Need an '=' after an attribute name");
                    }
                    break;

                case States.NEED_ATTRIBUTE_VALUE:
                    if (type == TokenType.STRING_LITERAL)
                    {
                        state = States.NEED_ATTRIBUTE_NAME;
                        string unescaped_attribute_value = ExpandEntityReferences(token);
                        curNode.AddAttribute(curAttributeName, unescaped_attribute_value);
                        curAttributeName = null;
                    }
                    else
                    {
                        throw new XmlException(lineNumber, "Line " + lineNumber + ": Must have an attribute value after the '=' in an XML node");
                    }
                    break;

                case States.NEED_CLOSURE_BRACKET:
                    if (type == TokenType.OPERATOR && token.Equals(">"))
                    {
                        // this node is done, and we don't have to check it
                        state = States.START;

                        if (stackTop != 0)
                        {
                            XmlNode parent = Peek();
                            parent.AddChild(curNode);
                        }
                        else
                        {
                            doc.AddChild(curNode);
                        }
                    }
                    else
                    {
                        throw new XmlException(lineNumber, "Line " + lineNumber + ": Must have a '>' after a closing '/' in an XML node");
                    }
                    break;

                case States.NEED_CLOSURE_NAME:
                    if (type == TokenType.NAME)
                    {
                        // pop the last XmlNode and make sure that this name matches.
                        // Otherwise we don't have balanced open and close tags
                        state = States.NEED_FINAL_BRACKET;
                        XmlNode xmln = Pop();
                        if (!token.Equals(xmln.Name))
                        {
                            throw new XmlException(lineNumber, "Line " + lineNumber + ": " + token + " does not match " + xmln.Name);
                        }
                    }
                    else
                    {
                        throw new XmlException(lineNumber, "Line " + lineNumber + ": Must have a name after an opening />");
                    }

                    break;

                case States.NEED_FINAL_BRACKET:
                    if (type == TokenType.OPERATOR && token.Equals(">"))
                    {
                        state = States.START;
                    }
                    else
                    {
                        throw new XmlException(lineNumber, "Line " + lineNumber + ": Must have a > after a closure tag's name");
                    }
                    break;

                case States.QUESTION_MARK_ELEMENT:
                    // just stay in this state until you see a '>'
                    while ('>' != ReadCharacter())
                    {
                        ;
                    }
                    state = States.START;
                    break;

                case States.GET_STRINGS:
                {
                    // stay in this state until you see a '<'
                    StringBuilder sb       = new StringBuilder();
                    XmlNode       prevNode = Peek();

                    if (type == TokenType.OPERATOR && token.Equals("<"))
                    {
                        throw new XmlException(lineNumber, "Unexpected tag beginning while in text state");
                    }

                    sb.Append(token);
                    while (PeekCharacter() != -1 && PeekCharacter() != '<')
                    {
                        sb.Append((char)ReadCharacter());
                    }

                    prevNode.AddText(sb.ToString());
                    state = States.START;
                }
                break;
                }
            }
            stream.Close();
            stream = null;
            return(doc);
        }