获取应用于Java中特定HTML类的CSS规则列表
我正在使用获取属于一组HTML类的特定CSS规则。目前,我在网站上已经有了一个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
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();
}
}
我尝试过输入,它似乎对我有效