示例#1
0
        /// <summary>Parses the selector items.</summary>
        /// <param name="selector">
        /// the selectors in the form of a
        /// <see cref="System.String"/>
        /// </param>
        /// <returns>
        /// the resulting list of
        /// <see cref="iText.StyledXmlParser.Css.Selector.Item.ICssSelectorItem"/>
        /// </returns>
        public static IList <ICssSelectorItem> ParseSelectorItems(String selector)
        {
            IList <ICssSelectorItem> selectorItems = new List <ICssSelectorItem>();
            CssSelectorParserMatch   match         = new CssSelectorParserMatch(selector, selectorPattern);
            bool tagSelectorDescription            = false;

            while (match.Success())
            {
                String selectorItem = match.GetValue();
                char   firstChar    = selectorItem[0];
                switch (firstChar)
                {
                case '#': {
                    match.Next();
                    selectorItems.Add(new CssIdSelectorItem(selectorItem.Substring(1)));
                    break;
                }

                case '.': {
                    match.Next();
                    selectorItems.Add(new CssClassSelectorItem(selectorItem.Substring(1)));
                    break;
                }

                case '[': {
                    match.Next();
                    selectorItems.Add(new CssAttributeSelectorItem(selectorItem));
                    break;
                }

                case ':': {
                    AppendPseudoSelector(selectorItems, selectorItem, match);
                    break;
                }

                case ' ':
                case '+':
                case '>':
                case '~': {
                    match.Next();
                    if (selectorItems.Count == 0)
                    {
                        throw new ArgumentException(MessageFormatUtil.Format("Invalid token detected in the start of the selector string: {0}"
                                                                             , firstChar));
                    }
                    ICssSelectorItem         lastItem = selectorItems[selectorItems.Count - 1];
                    CssSeparatorSelectorItem curItem  = new CssSeparatorSelectorItem(firstChar);
                    if (lastItem is CssSeparatorSelectorItem)
                    {
                        if (curItem.GetSeparator() == ' ')
                        {
                            break;
                        }
                        else
                        {
                            if (((CssSeparatorSelectorItem)lastItem).GetSeparator() == ' ')
                            {
                                selectorItems[selectorItems.Count - 1] = curItem;
                            }
                            else
                            {
                                throw new ArgumentException(MessageFormatUtil.Format("Invalid selector description. Two consequent characters occurred: {0}, {1}"
                                                                                     , ((CssSeparatorSelectorItem)lastItem).GetSeparator(), curItem.GetSeparator()));
                            }
                        }
                    }
                    else
                    {
                        selectorItems.Add(curItem);
                        tagSelectorDescription = false;
                    }
                    break;
                }

                default: {
                    //and case '*':
                    match.Next();
                    if (tagSelectorDescription)
                    {
                        throw new InvalidOperationException("Invalid selector string");
                    }
                    tagSelectorDescription = true;
                    selectorItems.Add(new CssTagSelectorItem(selectorItem));
                    break;
                }
                }
            }
            if (selectorItems.Count == 0)
            {
                throw new ArgumentException("Selector declaration is invalid");
            }
            return(selectorItems);
        }
示例#2
0
        /// <summary>
        /// Resolves a pseudo selector, appends it to list and updates
        /// <see cref="CssSelectorParserMatch"/>
        /// in process.
        /// </summary>
        /// <param name="selectorItems">list of items to which new selector will be added to</param>
        /// <param name="pseudoSelector">the pseudo selector</param>
        /// <param name="match">
        /// the corresponding
        /// <see cref="CssSelectorParserMatch"/>
        /// that will be updated.
        /// </param>
        private static void AppendPseudoSelector(IList <ICssSelectorItem> selectorItems, String pseudoSelector, CssSelectorParserMatch
                                                 match)
        {
            pseudoSelector = pseudoSelector.ToLowerInvariant();
            int    start  = match.GetIndex() + pseudoSelector.Length;
            String source = match.GetSource();

            if (start < source.Length && source[start] == '(')
            {
                int bracketDepth = 1;
                int curr         = start + 1;
                while (bracketDepth > 0 && curr < source.Length)
                {
                    if (source[curr] == '(')
                    {
                        ++bracketDepth;
                    }
                    else
                    {
                        if (source[curr] == ')')
                        {
                            --bracketDepth;
                        }
                        else
                        {
                            if (source[curr] == '"' || source[curr] == '\'')
                            {
                                curr = CssUtils.FindNextUnescapedChar(source, source[curr], curr + 1);
                            }
                        }
                    }
                    ++curr;
                }
                if (bracketDepth == 0)
                {
                    match.Next(curr);
                    pseudoSelector += source.JSubstring(start, curr);
                }
                else
                {
                    match.Next();
                }
            }
            else
            {
                match.Next();
            }

            /*
             * This :: notation is introduced by the current document in order to establish a discrimination between
             * pseudo-classes and pseudo-elements.
             * For compatibility with existing style sheets, user agents must also accept the previous one-colon
             * notation for pseudo-elements introduced in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and :after).
             * This compatibility is not allowed for the new pseudo-elements introduced in this specification.
             */
            if (pseudoSelector.StartsWith("::"))
            {
                selectorItems.Add(new CssPseudoElementSelectorItem(pseudoSelector.Substring(2)));
            }
            else
            {
                if (pseudoSelector.StartsWith(":") && legacyPseudoElements.Contains(pseudoSelector.Substring(1)))
                {
                    selectorItems.Add(new CssPseudoElementSelectorItem(pseudoSelector.Substring(1)));
                }
                else
                {
                    ICssSelectorItem pseudoClassSelectorItem = CssPseudoClassSelectorItem.Create(pseudoSelector.Substring(1));
                    if (pseudoClassSelectorItem == null)
                    {
                        throw new ArgumentException(MessageFormatUtil.Format(iText.StyledXmlParser.LogMessageConstant.UNSUPPORTED_PSEUDO_CSS_SELECTOR
                                                                             , pseudoSelector));
                    }
                    selectorItems.Add(pseudoClassSelectorItem);
                }
            }
        }