@Override
  public void visitXmlToken(XmlToken token) {
    IElementType tokenType = token.getTokenType();
    if (tokenType == XmlTokenType.XML_NAME || tokenType == XmlTokenType.XML_TAG_NAME) {
      PsiElement element = token.getPrevSibling();
      while (element instanceof PsiWhiteSpace) element = element.getPrevSibling();

      if (element instanceof XmlToken) {
        if (((XmlToken) element).getTokenType() == XmlTokenType.XML_START_TAG_START) {
          PsiElement parent = element.getParent();

          if (parent instanceof XmlTag
              && !(token.getNextSibling() instanceof OuterLanguageElement)) {
            checkTag((XmlTag) parent);
          }
        }
      } else {
        PsiElement parent = token.getParent();

        if (parent instanceof XmlAttribute
            && !(token.getNextSibling() instanceof OuterLanguageElement)) {
          checkAttribute((XmlAttribute) parent);
        }
      }
    } else if (tokenType == XmlTokenType.XML_DATA_CHARACTERS
        && token.getParent() instanceof XmlText) {
      if (token.textContains(']') && token.textContains('>')) {
        String s = token.getText();
        String marker = "]]>";
        int i = s.indexOf(marker);

        if (i != -1) { // TODO: fix
          TextRange textRange = token.getTextRange();
          int start = textRange.getStartOffset() + i;
          HighlightInfoType type =
              PsiTreeUtil.getParentOfType(token, XmlTag.class) instanceof HtmlTag
                  ? HighlightInfoType.WARNING
                  : HighlightInfoType.ERROR;
          HighlightInfo info =
              HighlightInfo.createHighlightInfo(
                  type,
                  start,
                  start + marker.length(),
                  XmlErrorMessages.message(
                      "cdata.end.should.not.appear.in.content.unless.to.mark.end.of.cdata.section"));
          addToResults(info);
        }
      }
    }
  }