innerHTML removes attribute quotes in Internet Exp

2019-01-11 11:53发布

问题:

When you get the innerHTML of a DOM node in IE, if there are no spaces in an attribute value, IE will remove the quotes around it, as demonstrated below:

<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>

In IE, the alert will read:

<DIV id=div2></DIV>

This is a problem, because I am passing this on to a processor that requires valid XHTML, and all attribute values must be quoted. Does anyone know of an easy way to work around this behavior in IE?

回答1:

IE innerHTML is very annoying indeed. I wrote this function for it, which may be helpfull? It quotes attributes and sets tagnames to lowercase. By the way, to make it even more annoying, IE's innerHTML doesn't remove quotes from non standard attributes.

Edit based on comments The function now processes more characters in attribute values and optionally converts attribute values to lower case. The function looks even more ugly now ;~). If you want to add or remove characters to the equation, edit the [a-zA-Z\.\:\[\]_\(\)\&\$\%#\@\!0-9]+[?\s+|?>] part of the regular expressions.

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;
}

Example key-value pairs that should work

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"


回答2:

Ah, the joy of trying to use XHTML in a browser that doesn't support it.

I'd just accept that you are going to get HTML back from the browser and put something in front of your XML processor that can input tag soup and output XHTML — HTML Tidy for example.



回答3:

I ran into this exact same problem just over a year ago, and solved it using InnerXHTML, a custom script written by someone far smarter than I am. It's basically a custom version of innerHTML that returns standard markup.



回答4:

I've tested this, and it works for most attributes, except those that are hyphenated, such as class=day-month-title. It ignores those attributes, and does not quote them.



回答5:

I might be couple year too late but here goes. Accepted answer might do what it promises but it's already Friday afternoon and I need something simpler nor I have time go it through. So here's my version which will just quote attribute values w/o quotes and it should be pretty trivial to extend it.

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;
});


回答6:

There is a quick and dirty workaround for this issue. I used it when working with jQuery templates. Just add a trailing space to the value of the attribute. Of course this does not make much sense with id that is used in the example, so here is another example involving jQuery, and jQuery templates:

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

Note the trailing space in the line <input value="${x} "/> without it, the example won't work on IE.



回答7:

did you tried with jquery ?

alert($('#div1').html());