@NotNull
 public XPathType getExpectedType(XPathExpression expr) {
   final XmlTag tag = PsiTreeUtil.getContextOfType(expr, XmlTag.class, true);
   if (tag != null && XsltSupport.isXsltTag(tag)) {
     final XsltElement element =
         XsltElementFactory.getInstance().wrapElement(tag, XsltElement.class);
     if (element instanceof XsltVariable) {
       return ((XsltVariable) element).getType();
     } else {
       final XmlAttribute attr = PsiTreeUtil.getContextOfType(expr, XmlAttribute.class, true);
       if (attr != null) {
         if (element instanceof XsltWithParam) {
           final XmlAttribute nameAttr = tag.getAttribute("name", null);
           if (nameAttr != null) {
             final XmlAttributeValue valueElement = nameAttr.getValueElement();
             if (valueElement != null) {
               final PsiReference[] references = valueElement.getReferences();
               for (PsiReference reference : references) {
                 final PsiElement psiElement = reference.resolve();
                 if (psiElement instanceof XsltVariable) {
                   return ((XsltVariable) psiElement).getType();
                 }
               }
             }
           }
         } else {
           final String name = attr.getName();
           return getTypeForTag(tag, name);
         }
       }
     }
   }
   return XPathType.UNKNOWN;
 }
 @NotNull
 public Map<String, String> getLocalNamespaceDeclarations() {
   Map<String, String> namespaces = new THashMap<String, String>();
   for (final XmlAttribute attribute : getAttributes()) {
     if (!attribute.isNamespaceDeclaration() || attribute.getValue() == null) continue;
     // xmlns -> "", xmlns:a -> a
     final String localName = attribute.getLocalName();
     namespaces.put(localName.equals(attribute.getName()) ? "" : localName, attribute.getValue());
   }
   return namespaces;
 }
  @Nullable
  private BidirectionalMap<String, String> computeNamespaceMap(PsiElement parent) {
    BidirectionalMap<String, String> map = null;
    if (hasNamespaceDeclarations()) {
      map = new BidirectionalMap<String, String>();
      final XmlAttribute[] attributes = getAttributes();

      for (final XmlAttribute attribute : attributes) {
        if (attribute.isNamespaceDeclaration()) {
          final String name = attribute.getName();
          int splitIndex = name.indexOf(':');
          final String value = getRealNs(attribute.getValue());

          if (value != null) {
            if (splitIndex < 0) {
              map.put("", value);
            } else {
              map.put(XmlUtil.findLocalNameByQualifiedName(name), value);
            }
          }
        }
      }
    }

    if (parent instanceof XmlDocument) {
      final XmlExtension extension = XmlExtension.getExtensionByElement(parent);
      if (extension != null) {
        final String[][] defaultNamespace =
            extension.getNamespacesFromDocument((XmlDocument) parent, map != null);
        if (defaultNamespace != null) {
          if (map == null) {
            map = new BidirectionalMap<String, String>();
          }
          for (final String[] prefix2ns : defaultNamespace) {
            map.put(prefix2ns[0], getRealNs(prefix2ns[1]));
          }
        }
      }
    }
    return map;
  }