@Test public void cssSelectorWithId() throws Exception { GeneratorContext context = getContext( "<div><div id=\"id1\">A <div>B <div>C</div></div></div></div>"); Document document = context.getDocument(); Element divA = document.select("div").get(1); Element divB = document.select("div").get(2); Element divC = document.select("div").get(3); assertThat(generateCssSelector(divA, context)).isEqualTo("#id1"); assertThat(generateCssSelector(divB, context)).isEqualTo("#id1 > div"); assertThat(generateCssSelector(divC, context)) .isEqualTo("#id1 > div > div"); }
public static String generateCssSelector(Element element, GeneratorContext context) { if (element.id().length() > 0) { return "#" + element.id(); } String tagName = element.tagName().replace(':', '|'); StringBuilder selector = new StringBuilder(tagName); addClasses(element, selector); Element parent = element.parent(); if (parent == null) { return selector.toString(); } if (parent.tagName().equals("body")) { if (context.getSource().contains("<body")) { return "body > " + selector.toString(); } else { return selector.toString(); } } String directChildrenSelector = ">" + selector.toString(); int numberOfDirectChildren = getNumberOfChildren(directChildrenSelector, parent); if (context.isNestedElement()) { int numberOfAllChildren = getNumberOfChildren(selector.toString(), parent); if (numberOfAllChildren != numberOfDirectChildren) { return null; } } if (numberOfDirectChildren > 1) { org.jsoup.select.Elements childrenWithSameSelector = parent .select(directChildrenSelector); String type = childrenWithSameSelector.get(0).tagName(); org.jsoup.select.Elements childrenWithSameType = parent .select(">" + type); int siblingIndex = childrenWithSameType.indexOf(element); if (anyPrecedingSiblingIsAStopElement(childrenWithSameType, siblingIndex)) { return null; } selector.append(String.format(":nth-of-type(%d)", siblingIndex + 1)); } if (hasReachedLastRepeaterElement(context, parent)) { return selector.toString(); } selector.insert(0, " > "); String parentSelector = generateCssSelector(parent, context); return parentSelector == null ? null : parentSelector + selector.toString(); }
Elements { public static String generateCssSelector(Element element, GeneratorContext context) { if (element.id().length() > 0) { return "#" + element.id(); } String tagName = element.tagName().replace(':', '|'); StringBuilder selector = new StringBuilder(tagName); addClasses(element, selector); Element parent = element.parent(); if (parent == null) { return selector.toString(); } if (parent.tagName().equals("body")) { if (context.getSource().contains("<body")) { return "body > " + selector.toString(); } else { return selector.toString(); } } String directChildrenSelector = ">" + selector.toString(); int numberOfDirectChildren = getNumberOfChildren(directChildrenSelector, parent); if (context.isNestedElement()) { int numberOfAllChildren = getNumberOfChildren(selector.toString(), parent); if (numberOfAllChildren != numberOfDirectChildren) { return null; } } if (numberOfDirectChildren > 1) { org.jsoup.select.Elements childrenWithSameSelector = parent .select(directChildrenSelector); String type = childrenWithSameSelector.get(0).tagName(); org.jsoup.select.Elements childrenWithSameType = parent .select(">" + type); int siblingIndex = childrenWithSameType.indexOf(element); if (anyPrecedingSiblingIsAStopElement(childrenWithSameType, siblingIndex)) { return null; } selector.append(String.format(":nth-of-type(%d)", siblingIndex + 1)); } if (hasReachedLastRepeaterElement(context, parent)) { return selector.toString(); } selector.insert(0, " > "); String parentSelector = generateCssSelector(parent, context); return parentSelector == null ? null : parentSelector + selector.toString(); } }
Elements { public static String generateCssSelector(Element element, GeneratorContext context) { if (element.id().length() > 0) { return "#" + element.id(); } String tagName = element.tagName().replace(':', '|'); StringBuilder selector = new StringBuilder(tagName); addClasses(element, selector); Element parent = element.parent(); if (parent == null) { return selector.toString(); } if (parent.tagName().equals("body")) { if (context.getSource().contains("<body")) { return "body > " + selector.toString(); } else { return selector.toString(); } } String directChildrenSelector = ">" + selector.toString(); int numberOfDirectChildren = getNumberOfChildren(directChildrenSelector, parent); if (context.isNestedElement()) { int numberOfAllChildren = getNumberOfChildren(selector.toString(), parent); if (numberOfAllChildren != numberOfDirectChildren) { return null; } } if (numberOfDirectChildren > 1) { org.jsoup.select.Elements childrenWithSameSelector = parent .select(directChildrenSelector); String type = childrenWithSameSelector.get(0).tagName(); org.jsoup.select.Elements childrenWithSameType = parent .select(">" + type); int siblingIndex = childrenWithSameType.indexOf(element); if (anyPrecedingSiblingIsAStopElement(childrenWithSameType, siblingIndex)) { return null; } selector.append(String.format(":nth-of-type(%d)", siblingIndex + 1)); } if (hasReachedLastRepeaterElement(context, parent)) { return selector.toString(); } selector.insert(0, " > "); String parentSelector = generateCssSelector(parent, context); return parentSelector == null ? null : parentSelector + selector.toString(); }  }
Elements { public static String generateCssSelector(Element element, GeneratorContext context) { if (element.id().length() > 0) { return "#" + element.id(); } String tagName = element.tagName().replace(':', '|'); StringBuilder selector = new StringBuilder(tagName); addClasses(element, selector); Element parent = element.parent(); if (parent == null) { return selector.toString(); } if (parent.tagName().equals("body")) { if (context.getSource().contains("<body")) { return "body > " + selector.toString(); } else { return selector.toString(); } } String directChildrenSelector = ">" + selector.toString(); int numberOfDirectChildren = getNumberOfChildren(directChildrenSelector, parent); if (context.isNestedElement()) { int numberOfAllChildren = getNumberOfChildren(selector.toString(), parent); if (numberOfAllChildren != numberOfDirectChildren) { return null; } } if (numberOfDirectChildren > 1) { org.jsoup.select.Elements childrenWithSameSelector = parent .select(directChildrenSelector); String type = childrenWithSameSelector.get(0).tagName(); org.jsoup.select.Elements childrenWithSameType = parent .select(">" + type); int siblingIndex = childrenWithSameType.indexOf(element); if (anyPrecedingSiblingIsAStopElement(childrenWithSameType, siblingIndex)) { return null; } selector.append(String.format(":nth-of-type(%d)", siblingIndex + 1)); } if (hasReachedLastRepeaterElement(context, parent)) { return selector.toString(); } selector.insert(0, " > "); String parentSelector = generateCssSelector(parent, context); return parentSelector == null ? null : parentSelector + selector.toString(); }  static boolean isButton(Element element); static boolean isLink(Element element); static String generateCssSelector(Element element,
			GeneratorContext context); }
Elements { public static String generateCssSelector(Element element, GeneratorContext context) { if (element.id().length() > 0) { return "#" + element.id(); } String tagName = element.tagName().replace(':', '|'); StringBuilder selector = new StringBuilder(tagName); addClasses(element, selector); Element parent = element.parent(); if (parent == null) { return selector.toString(); } if (parent.tagName().equals("body")) { if (context.getSource().contains("<body")) { return "body > " + selector.toString(); } else { return selector.toString(); } } String directChildrenSelector = ">" + selector.toString(); int numberOfDirectChildren = getNumberOfChildren(directChildrenSelector, parent); if (context.isNestedElement()) { int numberOfAllChildren = getNumberOfChildren(selector.toString(), parent); if (numberOfAllChildren != numberOfDirectChildren) { return null; } } if (numberOfDirectChildren > 1) { org.jsoup.select.Elements childrenWithSameSelector = parent .select(directChildrenSelector); String type = childrenWithSameSelector.get(0).tagName(); org.jsoup.select.Elements childrenWithSameType = parent .select(">" + type); int siblingIndex = childrenWithSameType.indexOf(element); if (anyPrecedingSiblingIsAStopElement(childrenWithSameType, siblingIndex)) { return null; } selector.append(String.format(":nth-of-type(%d)", siblingIndex + 1)); } if (hasReachedLastRepeaterElement(context, parent)) { return selector.toString(); } selector.insert(0, " > "); String parentSelector = generateCssSelector(parent, context); return parentSelector == null ? null : parentSelector + selector.toString(); }  static boolean isButton(Element element); static boolean isLink(Element element); static String generateCssSelector(Element element,
			GeneratorContext context);  }