示例#1
0
 /// <summary>
 /// Internal remove a node.
 /// </summary>
 internal void RemoveNode(HNode node)
 {
     // If node is alone, reset the list
     if (node.nextNode == node)
     {
         this.content = null;
     }
     else
     {
         // Find previous node
         var prev = node.nextNode;
         while (prev.nextNode != node)
         {
             prev = prev.nextNode;
         }
         // Clean the list
         prev.nextNode = node.nextNode;
         // If the node is the last, then prev become the last
         if (this.content == node)
         {
             this.content = prev;
         }
     }
     // Detach node
     node.parent   = null;
     node.nextNode = null;
 }
示例#2
0
        /// <summary>
        /// Enumerate deeper child nodes
        /// </summary>
        protected IEnumerable <HNode> GetDescendantNodes(bool self)
        {
            if (self)
            {
                yield return(this);
            }
            HNode n = this;

            while (true)
            {
                HContainer c = n as HContainer;
                HNode      first;
                if (c != null && (first = c.FirstNode) != null)
                {
                    n = first;
                }
                else
                {
                    while (n != null && n != this && n == n.parent.content)
                    {
                        n = n.parent;
                    }
                    if (n == null || n == this)
                    {
                        break;
                    }
                    n = n.nextNode;
                }
                yield return(n);
            }
        }
示例#3
0
 /// <summary>
 /// Serialize a node
 /// </summary>
 protected virtual void SerializeNode(HNode node, TextWriter writer)
 {
     if (node is HDocument)
     {
         SerializeDocument((HDocument)node, writer);
     }
     else if (node is HDocumentType)
     {
         SerializeDocumentType((HDocumentType)node, writer);
     }
     else if (node is HXmlDeclaration)
     {
         SerializeXmlDeclaration((HXmlDeclaration)node, writer);
     }
     else if (node is HComment)
     {
         SerializeComment((HComment)node, writer);
     }
     else if (node is HCData)
     {
         SerializeCData((HCData)node, writer);
     }
     else if (node is HText)
     {
         SerializeText((HText)node, writer);
     }
     else if (node is HElement)
     {
         SerializeElement((HElement)node, writer);
     }
 }
示例#4
0
 /// <summary>
 /// Internal insertion of string.
 /// </summary>
 void InsertString(HNode before, String s)
 {
     // Valid the string
     ValidateString(s);
     // If no content the we affect the texte
     if (content == null)
     {
         content = s;
     }
     else if (s.Length > 0)
     {
         if (before == null)
         {
             // If the content is a string, we concat them
             if (content is string)
             {
                 content = (string)content + s;
             }
             else
             {
                 // If the content is an HText node the we adding the string to the node
                 HText tn = content as HText;
                 if (tn != null && !(tn is HCData))
                 {
                     tn.value += s;
                 }
                 else
                 {
                     AppendNode(new HText(s));
                 }
             }
         }
         else if (before == FirstNodeRef)
         {
             // If the content is a string, we concat them
             if (content is string)
             {
                 content = s + (string)content;
             }
             else
             {
                 // If the content is an HText node the we adding the string to the node
                 HText tn = content as HText;
                 if (tn != null && !(tn is HCData))
                 {
                     tn.value = s + tn.value;
                 }
                 else
                 {
                     InsertNode(FirstNodeRef, new HText(s));
                 }
             }
         }
         else
         {
             InsertNode(before, new HText(s));
         }
     }
 }
示例#5
0
 /// <summary>
 /// Insert element after the target
 /// </summary>
 public static T InsertAfter <T>(this T element, HNode target) where T : HNode
 {
     if (element != null && target != null)
     {
         target.AddAfter(element);
     }
     return(element);
 }
示例#6
0
 /// <summary>
 /// Insert the set of elements after the target
 /// </summary>
 public static IEnumerable <T> InsertAfter <T>(this IEnumerable <T> elements, HNode target) where T : HNode
 {
     if (elements != null && target != null)
     {
         target.AddAfter(elements.ToArray());
     }
     return(elements);
 }
示例#7
0
 /// <summary>
 /// Insert <paramref name="node"/> before the <paramref name="before"/> node.
 /// </summary>
 /// <remarks>
 /// If previous is null then insert the node at the end of the list.
 /// </remarks>
 void InsertNode(HNode before, HNode node)
 {
     // Validate the node
     ValidateNode(node, this);
     // If the node have a parent we clone it
     if (node.Parent != null)
     {
         node = node.CloneNode();
     }
     else
     {
         // If node is the parent of this container, then we clone it
         HNode p = this;
         while (p.parent != null)
         {
             p = p.Parent;
         }
         if (node == p)
         {
             node = node.CloneNode();
         }
     }
     // Set the parent
     node.parent = this;
     // Content empty ?
     if (content == null)
     {
         node.nextNode = node;
         content       = node;
     }
     else if (before == null)
     {
         ConvertContentTextToNode();
         // Add at the end of the list
         node.nextNode             = ((HNode)content).nextNode;
         ((HNode)content).nextNode = node;
         content = node;
     }
     else if (before == FirstNodeRef)
     {
         ConvertContentTextToNode();
         // Add at the beginning of the list
         node.nextNode             = ((HNode)content).nextNode;
         ((HNode)content).nextNode = node;
     }
     else
     {
         // Search the 'previous' before node
         var previousBefore = before;
         while (previousBefore.nextNode != before)
         {
             previousBefore = previousBefore.nextNode;
         }
         // Insert the node to the list
         node.nextNode           = before;
         previousBefore.nextNode = node;
     }
 }
示例#8
0
 /// <summary>
 /// Can't accept a document or document type nodes
 /// </summary>
 internal override void ValidateNode(HNode node, HNode previous)
 {
     base.ValidateNode(node, previous);
     if (node is HDocument)
     {
         throw new ArgumentException("Can't add a document in a element.");
     }
     if (node is HDocumentType)
     {
         throw new ArgumentException("Can't add a document type in a element.");
     }
 }
示例#9
0
        /// <summary>
        /// Serialize a node
        /// </summary>
        public String SerializeNode(HNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            StringBuilder html = new StringBuilder();

            using (var writer = new StringWriter(html))
                SerializeNode(node, writer);
            return(html.ToString());
        }
示例#10
0
        /// <summary>
        /// Returns the nodes contained in this element.
        /// </summary>
        public IEnumerable <HNode> Nodes()
        {
            HNode n = LastNode;

            if (n != null)
            {
                do
                {
                    n = n.nextNode;
                    yield return(n);
                } while (n.parent == this && n != content);
            }
        }
示例#11
0
        /// <summary>
        /// Get all precedings siblings of the element
        /// </summary>
        public static IEnumerable <HNode> PrevAll(this HNode element)
        {
            if (element != null)
            {
                var p = element.PreviousNode;
                while (p != null)
                {
                    yield return(p);

                    p = p.PreviousNode;
                }
            }
        }
示例#12
0
        /// <summary>
        /// Get all next siblings of the element
        /// </summary>
        public static IEnumerable <HNode> NextAll(this HNode element)
        {
            if (element != null)
            {
                var p = element.NextNode;
                while (p != null)
                {
                    yield return(p);

                    p = p.NextNode;
                }
            }
        }
示例#13
0
        /// <summary>
        /// Insert a content before the <param name="insert" /> node.
        /// </summary>
        internal void Insert(HNode insert, object content)
        {
            if (content == null)
            {
                return;
            }
            HNode n = content as HNode;

            if (n != null)
            {
                InsertNode(insert, n);
                return;
            }
            string s = content as string;

            if (s != null)
            {
                InsertString(insert, s);
                return;
            }
            HAttribute a = content as HAttribute;

            if (a != null)
            {
                AddAttribute(a);
                return;
            }
            IEnumerable e = content as IEnumerable;

            if (e != null)
            {
                if (insert == FirstNodeRef)
                {
                    foreach (object obj in e.Cast <Object>().Reverse())
                    {
                        Insert(insert, obj);
                    }
                }
                else
                {
                    foreach (object obj in e)
                    {
                        Insert(insert, obj);
                    }
                }
                return;
            }
            InsertString(insert, content.ToString());
        }
示例#14
0
 /// <summary>
 /// Remove all nodes
 /// </summary>
 public void RemoveNodes()
 {
     if (this.content is HNode)
     {
         HNode node = (HNode)this.content;
         while (node != null)
         {
             node.parent = null;
             var n = node.nextNode;
             node.nextNode = null;
             node          = n;
         }
     }
     this.content = null;
 }
示例#15
0
        /// <summary>
        /// Enumerate all child elements
        /// </summary>
        protected IEnumerable <HElement> GetElements(String name)
        {
            HNode n = content as HNode;

            if (n != null)
            {
                do
                {
                    n = n.nextNode;
                    HElement e = n as HElement;
                    if (e != null && (name == null || String.Equals(e.Name, name, StringComparison.OrdinalIgnoreCase)))
                    {
                        yield return(e);
                    }
                } while (n.parent == this && n != content);
            }
        }
示例#16
0
        /// <summary>
        /// Find the node of a type
        /// </summary>
        /// <remarks>
        /// This is just an helper more fast than an GetElements().FirstOrDefault().
        /// </remarks>
        T FindFirstNode <T>() where T : HNode
        {
            HNode n = content as HNode;

            if (n != null)
            {
                do
                {
                    n = n.nextNode;
                    T e = n as T;
                    if (e != null)
                    {
                        return(e);
                    }
                } while (n != content);
            }
            return(null);
        }
示例#17
0
 internal HContainer(HContainer other)
 {
     if (other.content is string)
     {
         this.content = other.content;
     }
     else
     {
         HNode n = (HNode)other.content;
         if (n != null)
         {
             do
             {
                 n = n.nextNode;
                 AppendNode(n.CloneNode());
             } while (n != other.content);
         }
     }
 }
示例#18
0
        /// <summary>
        /// Enumerate deeper child elements
        /// </summary>
        protected IEnumerable <HElement> GetDescendants(String name, bool self)
        {
            if (self)
            {
                HElement e = (HElement)this;
                if (name == null || String.Equals(e.Name, name, StringComparison.OrdinalIgnoreCase))
                {
                    yield return(e);
                }
            }
            HNode      n = this;
            HContainer c = this;

            while (true)
            {
                if (c != null && c.content is HNode)
                {
                    n = ((HNode)c.content).nextNode;
                }
                else
                {
                    while (n != this && n == n.parent.content)
                    {
                        n = n.parent;
                    }
                    if (n == this)
                    {
                        break;
                    }
                    n = n.nextNode;
                }
                HElement e = n as HElement;
                if (e != null && (name == null || String.Equals(e.Name, name, StringComparison.OrdinalIgnoreCase)))
                {
                    yield return(e);
                }
                c = e;
            }
        }
示例#19
0
        internal override void ValidateNode(HNode node, HNode previous)
        {
            base.ValidateNode(node, previous);
            // Can't accept CData
            if (node is HCData)
            {
                throw new ArgumentException("Can't add CData in a document");
            }
            if (node is HDocument)
            {
                throw new ArgumentException("Can't add a document in a document");
            }

            // If node is a text, validate the string
            if (node is HText)
            {
                ValidateString(((HText)node).Value);
            }
            else if (node is HXmlDeclaration)
            {
                // If the xml declaration is defined, we can't add an another
                if (XmlDeclaration != null)
                {
                    throw new ArgumentException("Xml declaration is alreay defined.");
                }

                // We can't add a xml declaration after the document type
                if (DocumentType != null)
                {
                    throw new ArgumentException("Can't add a xml declaration after the document type.");
                }

                // We can't add a xml declaration after the root
                if (Root != null)
                {
                    throw new ArgumentException("Can't add a xml declaration after the root node.");
                }
            }
            else if (node is HDocumentType)
            {
                // If the document type is defined, we can't add an another
                if (DocumentType != null)
                {
                    throw new ArgumentException("Document type is alreay defined.");
                }

                // We can't add a document type after the root
                if (Root != null)
                {
                    throw new ArgumentException("Can't add a document type after the root node.");
                }
            }
            else if (node is HElement)
            {
                // If root is defined, then we can't add a new element
                if (Root != null)
                {
                    throw new ArgumentException("Root is already defined.");
                }
            }
        }
示例#20
0
 /// <summary>
 /// Add node at the end of the list.
 /// </summary>
 void AppendNode(HNode n)
 {
     InsertNode(null, n);
 }
示例#21
0
        /// <summary>
        /// Deserialize as a list of nodes
        /// </summary>
        public IEnumerable <HNode> Deserialize(TextReader reader, Func <Exception, bool> errorHandler = null)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            // Create the parser
            var parser = new HParser(reader);

            parser.RemoveUnknownOrInvalidEntities = this.RemoveUnknownOrInvalidEntities;
            var token = ParseNext(parser, errorHandler);
            Stack <HElement> opened       = new Stack <HElement>();
            HXmlDeclaration  currentXDecl = null;
            String           tag;
            HNode            tokenToReturns = null;

            while (token != null)
            {
                switch (token.TokenType)
                {
                case ParsedTokenType.Text:
                    var htxt = new HText(HEntity.HtmlDecode(((ParsedText)token).Text, RemoveUnknownOrInvalidEntities));
                    if (opened.Count > 0)
                    {
                        ProtectAddOnPeek(opened, htxt, errorHandler);
                    }
                    else
                    {
                        tokenToReturns = htxt;
                    }
                    break;

                case ParsedTokenType.CData:
                    var hcd = new HCData(((ParsedCData)token).Text);
                    if (opened.Count > 0)
                    {
                        ProtectAddOnPeek(opened, hcd, errorHandler);
                    }
                    else
                    {
                        tokenToReturns = hcd;
                    }
                    break;

                case ParsedTokenType.Comment:
                    var hcom = new HComment(HEntity.HtmlDecode(((ParsedComment)token).Text, RemoveUnknownOrInvalidEntities));
                    if (opened.Count > 0)
                    {
                        ProtectAddOnPeek(opened, hcom, errorHandler);
                    }
                    else
                    {
                        tokenToReturns = hcom;
                    }
                    break;

                case ParsedTokenType.OpenTag:
                    opened.Push(new HElement(((ParsedTag)token).TagName));
                    break;

                case ParsedTokenType.AutoClosedTag:
                    System.Diagnostics.Debug.Assert(opened.Count > 0, "Opened tags are empty when receiving AutoClosedTag.");
                    System.Diagnostics.Debug.Assert(opened.Peek().Name == ((ParsedTag)token).TagName, "AutoClosedTag and opened element are not same tag name.");
                    var actag = opened.Pop();
                    if (opened.Count > 0)
                    {
                        ProtectAddOnPeek(opened, actag, errorHandler);
                    }
                    else
                    {
                        tokenToReturns = actag;
                    }
                    break;

                case ParsedTokenType.CloseTag:
                    System.Diagnostics.Debug.Assert(opened.Count > 0, "Opened tags are empty when receiving CloseTag.");
                    System.Diagnostics.Debug.Assert(opened.Peek().Name == ((ParsedTag)token).TagName, "CloseTag and opened element are not same tag name.");
                    // Tag with text content
                    String tagName = opened.Peek().Name;
                    if (IsRawElement(tagName) || IsEscapableRawElement(tagName))
                    {
                        token = ParseContentTextNext(tagName, parser, errorHandler);
                        continue;
                    }
                    break;

                case ParsedTokenType.EndTag:
                    tag = ((ParsedTag)token).TagName;
                    HElement helm;
                    // Close all elements that not matching the tag
                    while (opened.Count > 0 && !String.Equals(opened.Peek().Name, tag, StringComparison.OrdinalIgnoreCase))
                    {
                        helm = opened.Pop();
                        if (opened.Count > 0)
                        {
                            ProtectAddOnPeek(opened, helm, errorHandler);
                        }
                        else
                        {
                            yield return(helm);
                        }
                    }
                    // If we are opened tag, then close it because we find our element
                    if (opened.Count > 0)
                    {
                        helm = opened.Pop();
                        if (opened.Count > 0)
                        {
                            ProtectAddOnPeek(opened, helm, errorHandler);
                        }
                        else
                        {
                            yield return(helm);
                        }
                    }
                    break;

                case ParsedTokenType.OpenProcessInstruction:
                    if (currentXDecl != null)
                    {
                        while ((token = ParseNext(parser, errorHandler)) != null && token.TokenType != ParsedTokenType.CloseProcessInstruction)
                        {
                            ;
                        }
                        ProcessError(new ParseError("XML declaration already opened."), errorHandler);
                    }
                    tag = ((ParsedTag)token).TagName;
                    if (!String.Equals("xml", tag, StringComparison.OrdinalIgnoreCase))
                    {
                        while ((token = ParseNext(parser, errorHandler)) != null && token.TokenType != ParsedTokenType.CloseProcessInstruction)
                        {
                            ;
                        }
                        ProcessError(new ParseError(String.Format("Unexpected '{0}' process instruction.", tag)), errorHandler);
                    }
                    currentXDecl = new HXmlDeclaration(null, null, null);
                    break;

                case ParsedTokenType.CloseProcessInstruction:
                    if (currentXDecl == null)
                    {
                        ProcessError(new ParseError("No XML declaration opened."), errorHandler);
                    }
                    else
                    {
                        if (opened.Count > 0)
                        {
                            ProtectAddOnPeek(opened, currentXDecl, errorHandler);
                        }
                        else
                        {
                            tokenToReturns = currentXDecl;
                        }
                    }
                    currentXDecl = null;
                    break;

                case ParsedTokenType.Doctype:
                    var vs  = ((ParsedDoctype)token).Values ?? new String[0];
                    var hdt = new HDocumentType(
                        vs.Length > 0 ? vs[0] : null,
                        vs.Length > 1 ? vs[1] : null,
                        vs.Length > 2 ? vs[2] : null,
                        vs.Length > 3 ? vs[3] : null
                        );
                    if (opened.Count > 0)
                    {
                        ProtectAddOnPeek(opened, hdt, errorHandler);
                    }
                    else
                    {
                        tokenToReturns = hdt;
                    }
                    break;

                case ParsedTokenType.Attribute:
                    var attr = (ParsedAttribute)token;
                    // Xml declaration ?
                    if (currentXDecl != null)
                    {
                        if (String.Equals("version", attr.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            currentXDecl.Version = attr.Value;
                        }
                        else if (String.Equals("encoding", attr.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            currentXDecl.Encoding = attr.Value;
                        }
                        else if (String.Equals("standalone", attr.Name, StringComparison.OrdinalIgnoreCase))
                        {
                            currentXDecl.Standalone = attr.Value;
                        }
                        else
                        {
                            ProcessError(new ParseError(String.Format("Invalid XML declaration attribute : ''", attr.Name)), errorHandler);
                        }
                    }
                    System.Diagnostics.Debug.Assert(opened.Count > 0, "No element opened for the attribtue.");
                    ProtectAddOnPeek(opened, new HAttribute(attr.Name, attr.Value), errorHandler);
                    break;
                    //default:
                    //    break;
                }
                // Returns a token if we have one
                if (tokenToReturns != null)
                {
                    yield return(tokenToReturns);

                    tokenToReturns = null;
                }
                // Next token
                token = ParseNext(parser, errorHandler);
            }
            // Close all opened elements
            while (opened.Count > 0)
            {
                yield return(opened.Pop());
            }
        }
示例#22
0
 /// <remarks>
 /// Validate insertion of the given node. previous is the node after which insertion
 /// will occur. previous == null means at beginning, previous == this means at end.
 /// </remarks>
 internal virtual void ValidateNode(HNode node, HNode previous)
 {
 }