public static boolean equals(@Nullable Element o1, @Nullable Element o2) {
    if (o1 == o2) {
      return true;
    }

    if (o1 == null || o2 == null || !Comparing.strEqual(o1.getName(), o2.getName()) || !attributesEqual(o1, o2)) {
      return false;
    }

    List<Content> content1 = o1.getContent();
    List<Content> content2 = o2.getContent();
    if (content1.size() != content2.size()) return false;
    for (int i = 0; i < content1.size(); i++) {
      Content c1 = content1.get(i);
      Content c2 = content2.get(i);
      if (c1 instanceof Text) {
        if (!(c2 instanceof Text) || !Comparing.strEqual(c1.getValue(), c2.getValue())) {
          return false;
        }
      }
      else if (c1 instanceof Element) {
        if (!(c2 instanceof Element) || !equals((Element)c1, (Element)c2)) {
          return false;
        }
      }
      else {
        throw new RuntimeException(c1.toString());
      }
    }
    return true;
  }
public static boolean equals(@Nullable Element o1, @Nullable Element o2)