Example #1
0
        /// <summary>
        /// Filters the attributes in the current tag.
        /// </summary>
        /// <param name="validTag">The valid tag, which specifies which attributes are valid.</param>
        public void FilterAttributes(ValidTag validTag)
        {
            // nothing to check against, so no valid attributes
            if (validTag == null)
            {
                this.attributes = null;
                return;
            }

            CaptureCollection atts   = match.Groups["attName"].Captures;
            CaptureCollection vals   = match.Groups["attVal"].Captures;
            CaptureCollection attVal = match.Groups["attNameValue"].Captures;

            StringBuilder sb = new StringBuilder();

            for (int i = 0, j = 0; i < atts.Count && j < vals.Count; i++)
            {
                string attName  = atts[i].Value.Trim();
                string attValue = vals[j].Value.Trim();

                if (validTag.IsValidAttribute(attName))
                {
                    // should be a complete att.
                    if (attName == attVal[i].Value.Trim())
                    {
                        continue;
                    }
                    sb.AppendFormat("{0}=\"{1}\" ", attName, attValue);
                }
                j++;
            }

            attributes = sb.ToString().Trim();
        }
        public void Add(ValidTag tag)
        {
            if (tag == null)
            {
                throw new ArgumentNullException("tag");
            }

            tags.Add(tag.Name, tag);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ValidTagCollection"/> class.
        /// </summary>
        /// <param name="tagsDefinition">The tags definition, defined as 'tag1@att1@att2,tag2@att3@att4'.</param>
        public ValidTagCollection(string tagsDefinition)
        {
            if (tagsDefinition == null || tagsDefinition.Length == 0)
            {
                return;
            }

            this.tagsDefinition = tagsDefinition;

            string[] splitTags = tagsDefinition.Split(',');

            foreach (string tagDef in splitTags)
            {
                ValidTag tag = new ValidTag(tagDef);
                tags.Add(tag.Name, tag);
            }
        }
        /// <summary>
        /// Adds the tag matches in an input string.
        /// </summary>
        /// <param name="matches">The tag matches from an input string.</param>
        public void Init(MatchCollection matches)
        {
            // param validation
            if (matches == null)
            {
                throw new ArgumentNullException("matches");
            }

            // holds the tags in the order they were matched
            store = new ArrayList(matches.Count);
            // pre-fill
            for (int i = 0; i < matches.Count; i++)
            {
                store.Add(null);
            }

            // holds the index of the matches that have not yet been matched
            Stack needMatching = new Stack();

            for (int i = 0; i < matches.Count; i++)
            {
                string name = matches[i].Groups["name"].Value;
                if (!allowedTags.IsValidTag(name))
                {
                    // illegal tag
                    store[i] = new MatchedTag(matches[i], false);
                    continue;
                }

                ValidTag validTag = allowedTags[name];

                // valid match
                // if its a self-closing tag, add to store
                bool self = matches[i].Groups["self"].Value.Length > 0;
                if (self)
                {
                    // this is the tag we use to write out the tag later
                    MatchedTag matchedTag = new MatchedTag(matches[i], true);
                    // check for invalid attributes
                    matchedTag.FilterAttributes(validTag);
                    // add to store
                    store[i] = matchedTag;

                    continue;
                }

                // end tag
                bool end = matches[i].Groups["end"].Value.Length > 0;
                if (end)
                {
                    if (needMatching.Count == 0)
                    {
                        // no opening tags for this closing tag, marks as invalid and go to the next
                        store[i] = new MatchedTag(matches[i], false);
                        continue;
                    }

                    // usually the opening tag will be followed by the closing tag
                    int peek = (int)needMatching.Peek();
                    if (String.Compare(matches[peek].Groups["name"].Value, name, true, CultureInfo.InvariantCulture) == 0)
                    {
                        // we have a match, add both to the store
                        store[i] = new MatchedTag(matches[i], true);

                        // filter the attr. for the opening tag
                        MatchedTag matchedTag = new MatchedTag(matches[peek], true);
                        matchedTag.FilterAttributes(validTag);

                        // add to store
                        store[peek] = matchedTag;
                        // remove from the queue
                        needMatching.Pop();
                        continue;
                    }

                    // enumerate through the stack to see if we can find a matching
                    // opening tag
                    int foundIndex = -1;
                    foreach (int j in needMatching)
                    {
                        // found a match
                        if (String.Compare(matches[j].Groups["name"].Value, name, true, CultureInfo.InvariantCulture) == 0)
                        {
                            foundIndex = j;
                            break;
                        }
                    }

                    if (foundIndex > -1)
                    {
                        while (needMatching.Count > 0 && (int)needMatching.Peek() >= foundIndex)
                        {
                            int pop = (int)needMatching.Pop();
                            if (pop == foundIndex)
                            {
                                // we have a match, add both to the store
                                store[i] = new MatchedTag(matches[i], true);

                                // filter the attr. for the opening tag
                                MatchedTag matchedTag = new MatchedTag(matches[pop], true);
                                matchedTag.FilterAttributes(validTag);

                                // add to store
                                store[pop] = matchedTag;
                            }
                            else
                            {
                                // this tag needs to be closed, since its between our opening and closing tags
                                store[pop] = new MatchedTag(matches[pop], true, true);
                            }
                        }
                    }
                    else
                    {
                        // nothing we could do with this tag, mark as invalid
                        store[i] = new MatchedTag(matches[i], false);
                    }
                    continue;
                }

                // opening tag add to queue until we find the matchin closing tag
                needMatching.Push(i);
            }

            // we have unmatched valid opening tags, make them self closing
            if (needMatching.Count > 0)
            {
                foreach (int i in needMatching)
                {
                    // filter the attr. for the opening tag
                    MatchedTag matchedTag = new MatchedTag(matches[i], true, true);
                    matchedTag.FilterAttributes(allowedTags[matchedTag.TagName]);

                    // add to store
                    store[i] = matchedTag;
                }
            }
        }