docs: function (elem)
      {
          var i, el, j, tag, attribute, value, css, cssAttrs, attr, cssName, cssValue;
          if (elem.nodeType == Strophe.ElementType.NORMAL) {
              tag = elem.nodeName;
              if(Strophe.XHTML.validTag(tag)) {
                  try {
                      el = Strophe.xmlElement(tag);
                      for(i = 0; i < Strophe.XHTML.attributes[tag].length; i++) {
                          attribute = Strophe.XHTML.attributes[tag][i];
                          value = elem.getAttribute(attribute);
                          if(typeof value == 'undefined' || value === null || value === '' || value === false || value === 0) {
                              continue;
                          }
                          if(attribute == 'style' && typeof value == 'object') {
                              if(typeof value.cssText != 'undefined') {
                                  value = value.cssText; // we're dealing with IE, need to get CSS out
                              }
                          }
                          // filter out invalid css styles
                          if(attribute == 'style') {
                              css = [];
                              cssAttrs = value.split(';');
                              for(j = 0; j < cssAttrs.length; j++) {
                                  attr = cssAttrs[j].split(':');
                                  cssName = attr[0].replace(/^\s*/, "").replace(/\s*$/, "").toLowerCase();
                                  if(Strophe.XHTML.validCSS(cssName)) {
                                      cssValue = attr[1].replace(/^\s*/, "").replace(/\s*$/, "");
                                      css.push(cssName + ': ' + cssValue);
                                  }
                              }
                              if(css.length > 0) {
                                  value = css.join('; ');
                                  el.setAttribute(attribute, value);
                              }
                          } else {
                              el.setAttribute(attribute, value);
                          }
                      }
  
                      for (i = 0; i < elem.childNodes.length; i++) {
                          el.appendChild(Strophe.createHtml(elem.childNodes[i]));
                      }
                  } catch(e) { // invalid elements
                    el = Strophe.xmlTextNode('');
                  }
              } else {
                  el = Strophe.xmlGenerator().createDocumentFragment();
                  for (i = 0; i < elem.childNodes.length; i++) {
                      el.appendChild(Strophe.createHtml(elem.childNodes[i]));
                  }
              }
          } else if (elem.nodeType == Strophe.ElementType.FRAGMENT) {
              el = Strophe.xmlGenerator().createDocumentFragment();
              for (i = 0; i < elem.childNodes.length; i++) {
                  el.appendChild(Strophe.createHtml(elem.childNodes[i]));
              }
          } else if (elem.nodeType == Strophe.ElementType.TEXT) {
              el = Strophe.xmlTextNode(elem.nodeValue);
          }
  
          return el;
      }