outerHTML undefined in IE
Asked Answered
C

3

7

My code gets JSON from an Ajax call, which contains XML, and goes through it reading some information.

Although the parsing of the XML runs fine in Chrome, it does not in IE, since in IE outerHTML returns undefined.

I have gone through several posts and tried several possible solutions with no success.

The JavaScript code is:

$.ajax({
    url: 'getJSONwithXML.do',
    type:'POST',
    data:'',
    dataType: 'json',
    cache: false
}).done(function(data) {
    var jsonResp = JSON.parse(data.data.respuesta);
    var parser = new DOMParser();
    var xmlDoc = parser.parseFromString(jsonResp,"text/xml");
    var texto = $(xmlDoc).find('texto').prop('outerHTML');
    console.log(texto); // <--- undefined in IE
    $('body').append('<div>' + texto + '</div>');
});

The xml I get under jsonResp is:

<?xml version="1.0" encoding="UTF-16"?>
<envio>
    <version>1.0.0</version>
    <anuncios>
        <remitente>
            <nodoRemitente>Nodo Remitente</nodoRemitente>
        </remitente>
        <anuncio>
            <emisor>
                <nodoEmisor>Nodo Emisor</nodoEmisor>
            </emisor>
            <metadatos>
                <id>16249</id>
            </metadatos>
            <contenido>
                <texto>
                    <p>
                        Notificación de prueba
                    </p>
                    <p>
                        Notificación de prueba
                    </p>
                    <p>
                        Notificación de prueba
                    </p>
                </texto>
            </contenido>
        </anuncio>
    </anuncios>
</envio>

Under Chrome or Fireforx, texto returns

<texto>
    <p>
        Notificación de prueba
    </p>
    <p>
        Notificación de prueba
    </p>
    <p>
        Notificación de prueba
    </p>
</texto>

which is what I want (the HTML code within texto tag), but in Internet Explorer I get undefined.

I have seen the textContent property but this is not what I want because it is not the HTML code.

Any ideas?

Capitalize answered 28/7, 2017 at 14:25 Comment(2)
If you be best if you could provide a minimal example of the XML you're receiving. Everyone's making guesses, which is great, but an actual definitive answer would require knowing what the structure is. Also. $(this).find('texto') will never return undefined, only a jQuery object with a length of 0.Disforest
Many thanks for the piece of advice regarding code improvement. updated. I have also edited my question and have provided the xml string I get under jsonRespCapitalize
P
18

Internet Explorer does not provide the outerHTML property (nor innerHTML) for nodes in an XML document. You can use XMLSerializer (in IE 9+) to work around that:

var node = $(xml).find('texto')[0]; // get DOM node
// Try outerHTML. If not available, use XMLSerializer
var texto = node.outerHTML || new XMLSerializer().serializeToString(node);

You'll note that the texto string may get the xmlns attribute for the root node. But I don't think that will matter for the way you use it.

Paly answered 31/7, 2017 at 8:15 Comment(2)
Many thanks @trincot!! what you suggestted worked like a charm!!Capitalize
@codenamezero, indeed. I removed the reference to IE11.Paly
C
0

Because you are using JQuery (as opposed to the standard DOM API methods that return a single DOM element), all your JQuery queries will return, at least, a JQuery wrapped set. That wrapped set may be populated or not, so you shouldn't be testing for the existence of the wrapped set, you should be testing for the contents of it. That is done by checking the length of the set.

Additionally, your tests to ensure that the element you want to get the outerHTML of are a bit convoluted. You will get "undefined" (as a string) when you test for typeof, so ensure that you use that when testing for undefined as a string.

See this example:

// There is no element with an id of "special" in this DOM
var result = $("#special");

// But, the JQuery query will still return a "wrapped set" container object
console.log(result === null);                         // false - there is a wrapped set

// You need to test for what's in the container:
console.log(result.length > 0);                       // false - the set is empty
console.log(typeof result[0] === "undefined");        // true  - nothing exists at position 0
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

So your code should check the length. And just remember that a length of 0 used in an if condition is "falsey" and will convert to false, while any other value is "truthy" and will convert to true:

if($(this).find('texto').length){
  debugger;
  var texto = $(this).find('texto').prop('outerHTML');
  .  . .
}

But since you may need access to that wrapped set more than once, you can use:

var el = $(this).find('texto');

if(el.length){
  debugger;
  var texto = el.prop('outerHTML');
  .  . .
}
Contra answered 28/7, 2017 at 14:33 Comment(5)
If you remove the not part of not or then you need to make it and - but it's just like saying 1+1=2 should 2=1+1Towle
@freedomn-m Yes, that was my original thought - Scott, I don't think your "Should be" section is any different from OP's code. Though I agree that the final snippet is the simple, elegant solution!Vest
if ($(this).find('texto')) will always return true. You need if ($(this).find('texto').length>0) (the code in the answer should be if (el.length>0)Towle
@freedomn-m Yes, good point. I've updated the answer to account for this.Contra
Many thansk for your pieces of advice regarding code improvements, but the point is that, no matter the way I check $(this).find('texto'), in Chrome and Firefox I get what I need from $(this).find('texto').prop('outerHTML'), but this does not work in Explorer.Capitalize
L
0

I think the problem is that you're using a mix of jQuery's HTML methods with an underlying DOMParser across XML. $(this).find(...) does a lot of work in various versions of IE to work around its flakey document model, but a lot of these don't play nice with XML.

IE supports XML, but it has issues with custom elements, so <texto> is fine in XML but unrecognised in HTML5.

To tell for certain we need to get into the exact version of jQuery and the document model IE is currently using (based on the document declaration).

However, an easy way around this would be to either switch out the jQuery for the XML parsing step, or switch from the native DOMParser to $.parseXML.

I'd try the former first - replace all the $(this).find(...) with this.getElementsByTagName(...).

Loisloise answered 28/7, 2017 at 14:34 Comment(6)
@freedomn-m It's not a micro optimisation (if we're going there I'd start by not using jQuery) - outerHTML is a DOM element property, not a jQuery function. $texto[0] is just a way of getting the DOM element rather than the wrapper to call the property directly.Loisloise
@Capitalize I've rewritten the answer following the clarifications in the question. I think this is an issue with IE's DOM parser and XML.Loisloise
I have also tried your solution but also gets Undefined text in Explorer browser. When inspecting $texto[0]there is no such method or property. No outerHTML nor html().Capitalize
@Capitalize I've rewritten the answer.Loisloise
OK. Many thanks. I will try again with your suggestion.Capitalize
Many thans @Loisloise for your suggestions, but what trincot suggested worked.Capitalize

© 2022 - 2024 — McMap. All rights reserved.