Cuando obtiene el innerHTML de un nodo DOM en IE, si no hay espacios en un valor de atributo, IE eliminará las comillas a su alrededor, como se muestra a continuación:

<html>
    <head>
        <title></title>
    </head>
    <body>
        <div id="div1"><div id="div2"></div></div>
        <script type="text/javascript">
            alert(document.getElementById("div1").innerHTML);
        </script>
    </body>
</html>

En IE, la alerta leerá:

<DIV id=div2></DIV>

Esto es un problema, porque paso esto a un procesador que requiere XHTML válido, y todos los valores de los atributos deben ser citados. ¿Alguien sabe de una manera fácil de evitar este comportamiento en IE?

13
Augustus 5 ago. 2009 a las 11:59

7 respuestas

La mejor respuesta

IE innerHTML es realmente muy molesto. Escribí esta función para ello, que puede ser útil. Cita atributos y establece nombres de etiquetas en minúsculas. Por cierto, para hacerlo aún más molesto, innerHTML de IE no elimina las comillas de los atributos no estándar.

Editar basado en comentarios La función ahora procesa más caracteres en los valores de los atributos y opcionalmente convierte los valores de los atributos en minúsculas. La función se ve aún más fea ahora; ~). Si desea agregar o eliminar caracteres a la ecuación, edite la parte [a-zA-Z\.\:\[\]_\(\)\&\$\%#\@\!0-9]+[?\s+|?>] de las expresiones regulares.

function ieInnerHTML(obj, convertToLowerCase) {
    var zz = obj.innerHTML ? String(obj.innerHTML) : obj
       ,z  = zz.match(/(<.+[^>])/g);    

    if (z) {
     for ( var i=0;i<z.length;(i=i+1) ){
      var y
         ,zSaved = z[i]
         ,attrRE = /\=[a-zA-Z\.\:\[\]_\(\)\&\$\%#\@\!0-9\/]+[?\s+|?>]/g
      ;

      z[i] = z[i]
              .replace(/([<|<\/].+?\w+).+[^>]/,
                 function(a){return a.toLowerCase();
               });
      y = z[i].match(attrRE);

      if (y){
        var j   = 0
           ,len = y.length
        while(j<len){
          var replaceRE = 
               /(\=)([a-zA-Z\.\:\[\]_\(\)\&\$\%#\@\!0-9\/]+)?([\s+|?>])/g
             ,replacer  = function(){
                  var args = Array.prototype.slice.call(arguments);
                  return '="'+(convertToLowerCase 
                          ? args[2].toLowerCase() 
                          : args[2])+'"'+args[3];
                };
          z[i] = z[i].replace(y[j],y[j].replace(replaceRE,replacer));
          j+=1;
        }
       }
       zz = zz.replace(zSaved,z[i]);
     }
   }
  return zz;
}

Ejemplo de pares clave-valor que deberían funcionar

data-mydata=return[somevalue] => data-mydata="return[somevalue]"
id=DEBUGGED:true => id="DEBUGGED:true" (or id="debugged:true" if you use the convertToLowerCase parameter)
someAttribute=Any.Thing.Goes => someAttribute="Any.Thing.Goes"
17
KooiInc 24 feb. 2012 a las 07:39

He probado esto y funciona para la mayoría de los atributos, excepto los que están separados por guiones, como class = day-month-title. Ignora esos atributos y no los cita.

2
joejoe 17 sep. 2009 a las 03:40

Intentaste con jquery?

alert($('#div1').html());
-6
Houssem 5 ago. 2009 a las 08:06

Podría llegar un par de años demasiado tarde, pero aquí va. La respuesta aceptada podría hacer lo que promete, pero ya es viernes por la tarde y necesito algo más simple ni tengo tiempo para hacerlo. Así que aquí está mi versión que solo citará valores de atributos sin comillas y debería ser bastante trivial extenderlo.

var t = "<svg id=foobar height=\"200\" width=\"746\"><g class=rules>";
t.replace(/([\w-]+)=([\w-]+)([ >])/g, function(str, $n, $v, $e, offset, s) {
    return $n + '="' + $v + '"' + $e;
});
2
andrei3k 7 oct. 2011 a las 13:27

Ah, la alegría de tratar de usar XHTML en un navegador que no lo admite.

Simplemente acepto que va a recuperar HTML del navegador y colocará algo en frente de su procesador XML que pueda ingresar sopa de etiquetas y generar XHTML - HTML Tidy por ejemplo.

5
Quentin 5 ago. 2009 a las 11:59

Hay una solución rápida y sucia para este problema. Lo usé cuando trabajaba con plantillas jQuery. Simplemente agregue un espacio final al valor del atributo. Por supuesto, esto no tiene mucho sentido con la identificación que se usa en el ejemplo, así que aquí hay otro ejemplo que involucra plantillas jQuery y jQuery:

http://jsfiddle.net/amamaenko/dW7Wh/5/

Tenga en cuenta el espacio final en la línea <input value="${x} "/> sin él, el ejemplo no funcionará en IE.

0
Anton Mamaenko 15 mar. 2011 a las 14:21

Me encontré con este mismo problema hace poco más de un año, y lo resolví usando InnerXHTML, un script personalizado escrito por alguien mucho más inteligente que yo. Básicamente es una versión personalizada de innerHTML que devuelve el marcado estándar.

3
Scottie 5 ago. 2009 a las 08:03