Ejemplo n.º 1
0
 private void Pop()
 {
   if (this.m_stack.Count > 1)
   {
     this.m_node = (Node)this.m_stack.Pop();
   }
 }
Ejemplo n.º 2
0
    private Node Push(string name, XmlNodeType nt, string value)
    {
      Node 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;
    }
Ejemplo n.º 3
0
 private 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.m_node = n2;
   return n2;
 }
Ejemplo n.º 4
0
 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;
   }
 }
Ejemplo n.º 5
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();
 }
Ejemplo n.º 6
0
    private void ValidateContent(Node node)
    {
      if (node.NodeType == XmlNodeType.Element)
      {
        if (!VerifyName(node.Name))
        {
          Pop();
          Push(null, XmlNodeType.Text, "<" + node.Name + ">");
          return;
        }
      }

      int i = 0;
      int top = this.m_stack.Count - 2;
      string name = (node.Name ?? "").ToUpperInvariant(); // DTD is in upper case
        
      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.                                  
        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;
            }
          }
        }
      }
      else if (this.DocType == "HTML")
      {
        bool voidElem;

        for (i = top; i > 0; i--)
        {
          Node n = (Node)this.m_stack[i];
          if (n.IsEmpty)
            continue; // we'll have to pop this one
          if ((i == 2) && string.Equals(n.Name, "BODY", StringComparison.OrdinalIgnoreCase)) // NOTE (steveb): never close the BODY tag too early
            break;
          else
          {
            voidElem = false;
            switch (n.Name.ToLowerInvariant())
            {
              case "area":
              case "base":
              case "br":
              case "col":
              case "embed":
              case "hr":
              case "img":
              case "input":
              case "keygen":
              case "link":
              case "meta":
              case "param":
              case "source":
              case "track":
              case "wbr":
                voidElem = true;
                break;
            }

            // 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.
            if (!voidElem) 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;
      }
    }
Ejemplo n.º 7
0
 private static 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;
     }
   }
 }
Ejemplo n.º 8
0
 private void Validate(Node node)
 {
   if (this.m_dtd != null)
   {
     ElementDecl e = this.m_dtd.FindElement(node.Name);
     if (e != null)
     {
       node.DtdType = e;
       if (e.ContentModel.DeclaredContent == DeclaredContent.EMPTY)
         node.IsEmpty = true;
     }
   }
 }
Ejemplo n.º 9
0
    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;
    }
Ejemplo n.º 10
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();
      }

      State 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;
      }

      bool 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();
            }
            Node 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 && !string.IsNullOrEmpty(this.SimulatedNode))
        {
          // Simulate a root element!
          this.m_node.CurrentState = this.m_state;
          Node root = Push(this.SimulatedNode, XmlNodeType.Element, null);
          SwapTopNodes(); // make root element 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;
    }