3

For some browsers, for some clients, jquery suddenly stopped parsing xml.

Example xml:

<?xml version="1.0" encoding="UTF-8"?>
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:example_namespace="https://mylink.com/wfs/example_namespace" xsi:schemaLocation="https://mylink.com/wfs/example_namespace mylink.com?SERVICE=WFS&amp;VERSION=1.0.0&amp;TYPENAME=example_namespace:TABLE&amp;REQUEST=DescribeFeatureType" numberMatched="unknown" numberReturned="1">
<gml:featureMember>
<example_namespace:TABLE fid="TABLE.15">
<example_namespace:ID>15</example_namespace:ID>
</example_namespace:TABLE>
</gml:featureMember>
</wfs:FeatureCollection>

Example jquery

$.get(link, function(data) { //Response is xml like in example.
console.log(data) //works as before
console.log($(data).find("featureMember").find("ID").text())
//Doesn't work now for some clients, but worked before.
})

EDIT:

More general example:

XML

<?xml version="1.0" encoding="UTF-8"?>
<a xmlns:c="http://www.example.com">
<c:b>TEST</c:b>
</a>

AND JS:

console.log($(data).find("b").text())

now returns: "", before returns: "TEST"

EDIT 2:

Similar problem: Cannot extract SOAP XML with jQuery

This code was originally working in Chrome last week and once Chrome updated to v60 it no longer does.

Yas
  • 351
  • 2
  • 17
  • Possible duplicate of [Chrome incorrect jQuery find() on XML result](https://stackoverflow.com/questions/43607774/chrome-incorrect-jquery-find-on-xml-result) – Andreas Aug 12 '17 at 08:46
  • Seems to be a [bug](https://bugs.chromium.org/p/chromium/issues/detail?id=738372) which should have been [fixed in v60](https://bugs.chromium.org/p/chromium/issues/detail?id=738372#c13) – Andreas Aug 12 '17 at 08:47
  • @Andreas How can the current Question possibly be a duplicate of linked Question? – guest271314 Aug 12 '17 at 08:55

2 Answers2

1

Pass data to $.parseXML() to get a #document, use .querySelector()

$.parseXML(data).querySelector("featureMember").querySelector("ID").textContent;

alternatively pass result of $.parseXML() to jQuery() and use .find()

$($.parseXML(data)).find("featureMember").find("ID").text();

jsfiddle https://jsfiddle.net/5fuLquth/

guest271314
  • 1
  • 15
  • 104
  • 177
  • Why `$.parseXML(data)` if _"console.log(data) //works as before"_ ? – Andreas Aug 12 '17 at 08:38
  • @Andreas What does _"`//works as before`"_ mean? `jQuery()` does not return a `#document` from which to call `.find()`. `jQuery()` returns a jQuery object containing a collection of `DOM` elements. `$.parseXML()` returns a `#document` – guest271314 Aug 12 '17 at 08:39
  • It returns a `#document` if the content-type is set properly: https://jsfiddle.net/datLxfot/ – Andreas Aug 12 '17 at 08:42
  • works as before means that "console.log(data)" return parsed XML like before update of chrome. – Yas Aug 12 '17 at 08:43
  • @Andreas What are you referencing by "It"? `jQuery()` does not return a `#document` – guest271314 Aug 12 '17 at 08:45
  • @Andreas Where do you set the `Content-Type` for `$.post()` call at linked jsfiddle? `$.get()` and `$.post()` expect content type to be set as string at last parameter to function call. – guest271314 Aug 12 '17 at 08:46
  • Just use `/echo/xml/` instead of `/echo/html/` – Andreas Aug 12 '17 at 08:48
  • @Andreas That does not set `Content-Type` for `$.get()` or `$.post()` – guest271314 Aug 12 '17 at 08:49
  • @Yas Chrome does not appear to be the issue. The issue is `jQuery()` returns a jQuery object from passed string containing a collection of elements, including `#text` nodes, not a `#document` or jQuery wrapped `[document]`. `$.parseXML()` returns a `#document` from which to search child nodes from. You can alternatively use `XMLHttpRequest()` to specifically set `.responseType` property to `"document"` to get an XML `#document` instead of an array-like object containing individual XML nodes. From where would you be trying to call `.find()` from? You would first need to filter the collection. – guest271314 Aug 12 '17 at 09:08
  • data.querySelector("featureMember").querySelector("ID").textContent works, but $(data).find("featureMember").find("ID").text(); doesn't work – Yas Aug 12 '17 at 09:19
  • You need to pass `data` to `$.parseXML()` first, then pass `$.parseXML()` to `jQuery()` `$($.parseXML(data))` to get a reference to the XML `#document` wrapped as a jQuery object, as demonstrated at code at Answer. [`jQuery()`](https://api.jquery.com/jquery) call alone does not convert text into a `#document`. `.find()` searches for descendants, `jQuery()` returns an object containing a collection of elements, essentially siblings within the array-like object which may include `comment` and `#text` nodes before `document.documentElement` of XML. You would need to filter root element first – guest271314 Aug 12 '17 at 09:24
  • @Yas You can use `console` to determine for yourself what `jQuery(data)` returns, and how to properly filter the object for the node value that you are trying to retrieve from the array-like object. – guest271314 Aug 12 '17 at 09:32
1

Parsing XML using jQuery in this way has some browser compatibility bugs I believe. This has been a won't fix jquery bug previously.

When there are namespaces in the xml you can use jquery selectors like the below by escaping the colon:

.find('gml\\:featureMember')

or using nodeName:

.find('[nodeName="gml:featureMember"]')

See demo below:

var xml=`<?xml version="1.0" encoding="UTF-8"?><wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:example_namespace="https://mylink.com/wfs/example_namespace" xsi:schemaLocation="https://mylink.com/wfs/example_namespace mylink.com?SERVICE=WFS&amp;VERSION=1.0.0&amp;TYPENAME=example_namespace:TABLE&amp;REQUEST=DescribeFeatureType" numberMatched="unknown" numberReturned="1"><gml:featureMember><example_namespace:TABLE fid="TABLE.15"><example_namespace:ID>15</example_namespace:ID></example_namespace:TABLE></gml:featureMember></wfs:FeatureCollection>`;

console.log($(xml)
  .find('gml\\:featureMember')
  .find("example_namespace\\:ID").text());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
kukkuz
  • 41,512
  • 6
  • 59
  • 95