@Nullable
  private XmlNSDescriptor getNsDescriptorFormDocType(
      final XmlDoctype doctype, final XmlFile containingFile, final boolean forHtml) {
    XmlNSDescriptor descriptor = getNSDescriptorFromMetaData(doctype.getMarkupDecl(), true);

    final String filePath = getFilePathForLogging(containingFile);

    final String dtdUri = XmlUtil.getDtdUri(doctype);
    LOG.debug(
        "DTD url for doctype " + doctype.getText() + " in file " + filePath + " is " + dtdUri);

    if (dtdUri != null && !dtdUri.isEmpty()) {
      XmlFile xmlFile = XmlUtil.findNamespace(containingFile, dtdUri);
      if (xmlFile == null) {
        // try to auto-detect it
        xmlFile = XmlNamespaceIndex.guessDtd(dtdUri, containingFile);
      }
      final String schemaFilePath = getFilePathForLogging(xmlFile);

      LOG.debug("Schema file for " + filePath + " is " + schemaFilePath);

      XmlNSDescriptor descriptorFromDtd =
          getNSDescriptorFromMetaData(xmlFile == null ? null : xmlFile.getDocument(), forHtml);

      LOG.debug(
          "Descriptor from meta data for schema file "
              + schemaFilePath
              + " is "
              + (descriptorFromDtd != null
                  ? descriptorFromDtd.getClass().getCanonicalName()
                  : "NULL"));

      if (descriptor != null && descriptorFromDtd != null) {
        descriptor =
            new XmlNSDescriptorSequence(new XmlNSDescriptor[] {descriptor, descriptorFromDtd});
      } else if (descriptorFromDtd != null) {
        descriptor = descriptorFromDtd;
      }
    }
    return descriptor;
  }
  @Override
  public boolean execute(
      @NotNull final PsiElement queryParameters, @NotNull final Processor<PsiElement> consumer) {
    if (queryParameters instanceof XmlTagImpl) {
      final XmlTagImpl xml = (XmlTagImpl) queryParameters;
      if (isTypeElement(xml)) {
        final Collection<SchemaTypeInfo> infos =
            ApplicationManager.getApplication()
                .runReadAction(
                    new Computable<Collection<SchemaTypeInfo>>() {

                      @Override
                      public Collection<SchemaTypeInfo> compute() {
                        return gatherInheritors(xml);
                      }
                    });

        if (infos != null && !infos.isEmpty()) {
          final Project project = XmlUtil.getContainingFile(xml).getProject();
          final Module module = ModuleUtil.findModuleForPsiElement(queryParameters);
          // if (module == null) return false;

          final XmlFile file = XmlUtil.getContainingFile(xml);
          final VirtualFile vf = file.getVirtualFile();
          String thisNs = XmlNamespaceIndex.getNamespace(vf, project);
          thisNs = thisNs == null ? getDefaultNs(file) : thisNs;
          // so thisNs can be null
          if (thisNs == null) return false;
          final ArrayList<SchemaTypeInfo> infosLst = new ArrayList<SchemaTypeInfo>(infos);
          Collections.sort(infosLst);
          final Map<String, Set<XmlFile>> nsMap = new HashMap<String, Set<XmlFile>>();
          for (final SchemaTypeInfo info : infosLst) {
            Set<XmlFile> targetFiles = nsMap.get(info.getNamespaceUri());
            if (targetFiles == null) {
              targetFiles = new HashSet<XmlFile>();
              if (Comparing.equal(info.getNamespaceUri(), thisNs)) {
                targetFiles.add(file);
              }
              final Collection<XmlFile> files =
                  ApplicationManager.getApplication()
                      .runReadAction(
                          new Computable<Collection<XmlFile>>() {
                            @Override
                            public Collection<XmlFile> compute() {
                              return XmlUtil.findNSFilesByURI(
                                  info.getNamespaceUri(), project, module);
                            }
                          });
              if (files != null) {
                targetFiles.addAll(files);
              }
              nsMap.put(info.getNamespaceUri(), targetFiles);
            }
            if (!targetFiles.isEmpty()) {
              for (final XmlFile targetFile : targetFiles) {
                ApplicationManager.getApplication()
                    .runReadAction(
                        new Runnable() {
                          @Override
                          public void run() {
                            final String prefixByURI =
                                XmlUtil.findNamespacePrefixByURI(
                                    targetFile, info.getNamespaceUri());
                            if (prefixByURI == null) return;
                            final PsiElementProcessor processor =
                                new PsiElementProcessor() {
                                  @Override
                                  public boolean execute(@NotNull PsiElement element) {
                                    if (element instanceof XmlTagImpl) {
                                      if (isCertainTypeElement(
                                              (XmlTagImpl) element, info.getTagName(), prefixByURI)
                                          || isElementWithEmbeddedType(
                                              (XmlTagImpl) element,
                                              info.getTagName(),
                                              prefixByURI)) {
                                        consumer.process(element);
                                        return false;
                                      }
                                    }
                                    return true;
                                  }
                                };
                            XmlUtil.processXmlElements(targetFile, processor, true);
                          }
                        });
              }
            }
          }
        }
      }
    }
    return true;
  }