Example #1
0
        /// <summary>
        /// 创建选择器
        /// </summary>
        /// <param name="expression">选择器表达式</param>
        /// <returns>选择器实例</returns>
        public static ICssSelector Create(string expression)
        {
            if (selectorCache.ContainsKey(expression))
            {
                return(selectorCache[expression]);
            }

            var match = casecadingSelectorRegex.Match(expression);

            if (!match.Success)
            {
                throw new FormatException();
            }


            ICssSelector selector = CssElementSelector.Create(match.Groups["leftSelector"].Value);

            foreach (var extraCapture in match.Groups["extra"].Captures.Cast <Capture>())
            {
                var relative      = extraCapture.FindCaptures(match.Groups["relative"]).Single().Value.Trim();
                var rightSelector = extraCapture.FindCaptures(match.Groups["rightSelector"]).Single().Value.Trim();

                selector = new CssCasecadingSelector(selector, relative, CssElementSelector.Create(rightSelector));
            }

            lock ( _cacheSync )
            {
                selectorCache[expression] = selector;
            }

            return(selector);
        }
Example #2
0
        /// <summary>
        /// 创建一个 CSS 选择器
        /// </summary>
        /// <param name="expression">选择器表达式</param>
        /// <param name="scope">范畴限定</param>
        /// <returns>选择器</returns>
        public static ICssSelector Create(string expression, IHtmlContainer scope)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }


            ICssSelector[] selectors;

            if (_selectorCache.ContainsKey(expression))
            {
                selectors = _selectorCache[expression];
            }

            else
            {
                var match = cssSelectorRegex.Match(expression);

                if (!match.Success)
                {
                    throw new FormatException("无法识别的CSS选择器");
                }

                selectors = match.Groups["selector"].Captures.Cast <Capture>().Select(c => CssCasecadingSelector.Create(c.Value)).ToArray();
            }

            lock ( _cacheSync )
            {
                _selectorCache[expression] = selectors;
            }


            return(new CssMultipleSelector(selectors.Select(s => CssCasecadingSelector.Create(s, scope)).ToArray()));
        }
Example #3
0
        /// <summary>
        /// 创建带范畴限定的选择器
        /// </summary>
        /// <param name="expression">选择器表达式</param>
        /// <param name="scope">范畴限定,上溯时不超出此范畴</param>
        /// <returns>带范畴限定的层叠选择器</returns>
        public static ISelector Create(IHtmlContainer scope, string expression)
        {
            if (scope == null)
            {
                throw new ArgumentNullException("scope");
            }

            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            return(CssCasecadingSelector.Create(new CssAncetorRelativeSelector(new ContainerRestrict(scope)), CssParser.ParseSelector(expression)));
        }
Example #4
0
        /// <summary>
        /// 合并两个关系选择器
        /// </summary>
        /// <param name="left">左关系选择器</param>
        /// <param name="right">右关系选择器</param>
        /// <returns>合并后的关系选择器</returns>
        public static CssRelativeSelector Combine(CssRelativeSelector left, CssRelativeSelector right)
        {
            if (left == null)
            {
                throw new ArgumentNullException("left");
            }

            if (right == null)
            {
                throw new ArgumentNullException("right");
            }


            var selector   = right.LeftSelector;
            var combinator = right.Combinator;


            var casecadingSelector = selector as CssCasecadingSelector;

            if (casecadingSelector != null)                                                                          //如果右边关系选择器的左选择器是一个层叠选择器
            {
                return(CreateRelativeSelector(CssCasecadingSelector.Combine(left, casecadingSelector), combinator)); //将层叠选择器与左边的关系选择器合并,得到一个新的层叠选择器,再根据结合符创建新的关系选择器。
            }

            /*
             * 举例说明如下:
             * 假设左关系选择器是 p>,右关系选择器是 div>ul>li+
             * 则右关系选择器的左选择器(selector)是div>ul>li,结合符(combinator)是+。
             * 将selector与左边的关系选择器合并,得到:p>div>ul>li,再与结合符结合得到新的关系选择器:p>div>ul>li+
             */

            var elementSelector = selector as CssElementSelector;

            if (elementSelector != null)
            {
                return(CreateRelativeSelector(new CssCasecadingSelector(left, elementSelector), combinator));
            }


            throw new NotSupportedException();
        }
Example #5
0
        /// <summary>
        /// 在元素集所有子代元素中使用 CSS 选择器选出符合要求的元素
        /// </summary>
        /// <param name="elements">作为选择范围的元素集</param>
        /// <param name="expression">CSS 选择器表达式</param>
        /// <returns>符合选择器的所有子代</returns>
        public static IEnumerable <IHtmlElement> Find(this IEnumerable <IHtmlElement> elements, string expression)
        {
            if (!elements.Any())
            {
                return(Enumerable.Empty <IHtmlElement>());
            }

            if (elements.IsSingle())
            {
                return(elements.Single().Find(expression));
            }

            var document = elements.First().Document;

            if (elements.Any(e => !e.Document.Equals(document)))
            {
                throw new InvalidOperationException("不支持在不同的文档中搜索");
            }

            var selector = CssCasecadingSelector.Create(expression, elements);

            return(selector.Filter(document.Descendants()));
        }
Example #6
0
 /// <summary>
 /// 创建层叠选择器
 /// </summary>
 /// <param name="leftSelector">左选择器</param>
 /// <param name="combanitor">结合符</param>
 /// <param name="rightSelector">右选择器</param>
 /// <returns>层叠选择器</returns>
 private static ISelector CreateCasecadingSelector(ISelector leftSelector, char combanitor, CssElementSelector rightSelector)
 {
     return(CssCasecadingSelector.Create(leftSelector, combanitor, rightSelector));
 }
Example #7
0
 /// <summary>
 /// 合并关系选择器和层叠选择器
 /// </summary>
 /// <param name="relativeSelector">关系选择器</param>
 /// <param name="selector">层叠选择器</param>
 /// <returns></returns>
 internal static CssCasecadingSelector Combine(CssRelativeSelector relativeSelector, CssCasecadingSelector selector)
 {
     relativeSelector = Combine(relativeSelector, selector.RelativeSelector);
     return(new CssCasecadingSelector(relativeSelector, selector.LastSelector));
 }
Example #8
0
 /// <summary>
 /// 调用此方法预热选择器
 /// </summary>
 public static void WarmUp()
 {
     cssSelectorRegex.IsMatch("");
     CssCasecadingSelector.WarmUp();
 }
Example #9
0
 /// <summary>
 /// 合并关系选择器和层叠选择器
 /// </summary>
 /// <param name="relativeSelector">关系选择器</param>
 /// <param name="selector">层叠选择器</param>
 /// <returns></returns>
 internal static CssCasecadingSelector Combine( CssRelativeSelector relativeSelector, CssCasecadingSelector selector )
 {
   relativeSelector = Combine( relativeSelector, selector.RelativeSelector );
   return new CssCasecadingSelector( relativeSelector, selector.LastSelector );
 }
Example #10
0
 public static ICssSelector Combine(CssRelativeSelector relativeSelector, CssMultipleSelector multipleSelector)
 {
     return(new CssMultipleSelector(multipleSelector._selectors.Select(selector => CssCasecadingSelector.Create(relativeSelector, selector)).ToArray()));
 }