获取应用于Java中特定HTML类的CSS规则列表

获取应用于Java中特定HTML类的CSS规则列表,java,css-parsing,Java,Css Parsing,我正在使用获取属于一组HTML类的特定CSS规则。目前,我在网站上已经有了一个CSS规则列表,但是我不知道如何获得我正在寻找的规则 当前代码: InputSource inputSource = new InputSource("example.com"); CSSOMParser parser = new CSSOMParser(new SACParserCSS3()); ErrorHandler errorHandler = new CSSErrorHandler(); parser.se

我正在使用获取属于一组HTML类的特定CSS规则。目前,我在网站上已经有了一个CSS规则列表,但是我不知道如何获得我正在寻找的规则

当前代码:

InputSource inputSource = new InputSource("example.com");
CSSOMParser parser = new CSSOMParser(new SACParserCSS3());

ErrorHandler errorHandler = new CSSErrorHandler();
parser.setErrorHandler(errorHandler);

CSSStyleSheet sheet = parser.parseStyleSheet(inputSource, null, null);

CSSRuleList rules = sheet.getCssRules();
我的选择之一是做一个for循环,但我不愿意这样做,因为 A.如果一个页面中有数百条规则,那么速度会很慢。 B似乎没有方法获取规则的类名


如果您有任何帮助,我们将不胜感激。请添加一个:CSS已经被您的代码解析,因此您只需查看性能方面可以接受的选择器即可

添加b:CSSStyleRule接口缺少getSelectors方法,但CSSStyleRuleImpl有它。所以你可以试着做点什么:

scanRules(rules, name -> name.contains("e"), 
    (names, rule) -> System.out.println(
            new TreeSet<>(names) + " --> " + rule.getCssText()));
使用递归辅助方法

// scan CSS rules including rules contained in media rules 
void scanRules(CSSRuleList rules, Predicate<String> classNameTest,
        BiConsumer<Set<String>, CSSStyleRule> ruleAction) {
    for (int ri = 0; ri < rules.getLength(); ri++) {
        CSSRule rule = rules.item(ri);
        if (rule.getType() == CSSRule.MEDIA_RULE) {
            CSSMediaRule mr = (CSSMediaRule) rule;
            scanRules(mr.getCssRules(), classNameTest, ruleAction);
        } else if (rule.getType() == CSSRule.STYLE_RULE) {
            CSSStyleRuleImpl styleRule = (CSSStyleRuleImpl) rule;
            SelectorList selectors = styleRule.getSelectors();
            // if (!styleRule.getSelectorText().contains(".name"))
            //  continue; // selector text test might cause speed up...
            for (int si = 0; si < selectors.getLength(); si++) {
                Selector selector = selectors.item(si);
                Set<String> classNames = classNamesInSelectorMatching(selector, classNameTest);
                if (!classNames.isEmpty()) 
                    ruleAction.accept(classNames, styleRule);
            }
        }
    }
}

// find matching class names in given (potentially complex) selector
Set<String> classNamesInSelectorMatching(Selector selector,
        Predicate<String> nameMatches) {
    switch (selector.getSelectorType()) {
        case Selector.SAC_CHILD_SELECTOR:
        case Selector.SAC_DESCENDANT_SELECTOR:
        case Selector.SAC_DIRECT_ADJACENT_SELECTOR: {
            DescendantSelector ds = (DescendantSelector) selector;
            Set<String> set = new HashSet<>();
            set.addAll(classNamesInSelectorMatching(ds.getAncestorSelector(), nameMatches));
            set.addAll(classNamesInSelectorMatching(ds.getSimpleSelector(), nameMatches));
            return set;
        }
        case Selector.SAC_NEGATIVE_SELECTOR: {
            NegativeSelector ns = (NegativeSelector) selector;
            return classNamesInSelectorMatching(ns.getSimpleSelector(), nameMatches);
        }
        case Selector.SAC_CONDITIONAL_SELECTOR: {
            ConditionalSelector ns = (ConditionalSelector) selector;
            return classNamesInConditionMatching(ns.getCondition(), nameMatches);
        }
        default:
            return Collections.emptySet();
    }
}

// find matching class names in given (potentially complex) condition
Set<String> classNamesInConditionMatching(Condition condition,
        Predicate<String> nameMatches) {
    switch (condition.getConditionType()) {
        case Condition.SAC_CLASS_CONDITION: {
            AttributeCondition ac = (AttributeCondition) condition;
            if (nameMatches.test(ac.getValue()))
                return Collections.singleton(ac.getValue());
            else
                return Collections.emptySet();
        }
        case Condition.SAC_AND_CONDITION:
        case Condition.SAC_OR_CONDITION: {
            CombinatorCondition cc = (CombinatorCondition) condition;
            Set<String> set = new HashSet<>();
            set.addAll(classNamesInConditionMatching(cc.getFirstCondition(), nameMatches));
            set.addAll(classNamesInConditionMatching(cc.getSecondCondition(), nameMatches));
            return set;
        }
        case Condition.SAC_NEGATIVE_CONDITION: {
            NegativeCondition nc = (NegativeCondition) condition;
            return classNamesInConditionMatching(nc.getCondition(), nameMatches);
        }
        default:
            return Collections.emptySet();
    }
}
我尝试过输入,它似乎对我有效