Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-7918] MobileWeb: XML parity issue

GitHub Issuen/a
TypeBug
PriorityHigh
StatusClosed
ResolutionInvalid
Resolution Date2012-03-13T09:23:46.000+0000
Affected Version/sRelease 2.0.0
Fix Version/sn/a
ComponentsMobileWeb
Labelsdr-list, parity
ReporterTony Lukasavage
AssigneeNeeraj Gupta
Created2012-03-07T14:42:42.000+0000
Updated2014-01-28T23:57:34.000+0000

Description

Problem

XML parsing differs between iOS/Android and mobile web. The test case below shows the manner in which I encountered it. In the case of Android and iOS, to retrieve the text of an XML element, one only needs to access the text property of the Element object. In mobile web, though, it is necessary to get the first child of the Element, presumably the text node, then grab the nodeValue attribute of this child node. The text property will not work in this case.

Test Case

feed.xml (attached) is a copy of the remote feed used by iOS and Android in this case. Cross origin rules prevent me from making the calls directly to the remote RSS feed with mobile web, and iOS and Android can't use HTTPClient to access local files.
var url = Ti.Platform.osname === 'mobileweb' ? '/feed.xml' : 'http://feeds.mashable.com/Mashable?format=xml';
var win = Ti.UI.createWindow({
	backgroundColor: '#fff',
	fullscreen: false,
	exitOnClose: true
});
var button = Ti.UI.createButton({
	title: 'send request',
	height: 40,
	width: 120
});
win.add(button);

var getRssText = function(item, key) {
	// Prints title for ios and android, null on mobile web
	Ti.API.info(item.getElementsByTagName(key).item(0).text);
	
	// Prints title for mobile web, fails on android and ios
	// Ti.API.info(item.getElementsByTagName(key).item(0).childNodes[0].nodeValue);
}

button.addEventListener('click', function(e) {
	var xhr = Titanium.Network.createHTTPClient();	
	xhr.open('GET', url);
	
	xhr.onload = function(e) {
		var xml = this.responseXML;
		var items = xml.documentElement.getElementsByTagName("item");
		var data = [];

		for (var i = 0; i < items.length; i++) {
			var item = items.item(i);
			getRssText(item, 'title');
		}
	};
	xhr.onerror = function(e) {
		alert(e.error);
	};
	xhr.send();	
});

win.open();

Proposed Solution

Make the functionality of the XML parsing work like iOS and Android as that is what Titanium developers have come to expect.

Attachments

FileDateSize
feed.xml2012-03-07T14:42:42.000+0000301216

Comments

  1. Chris Barber 2012-03-09

    This is actually because the Ti.Network.HttpClient is not setting responseXML correctly. It's currently setting it to the same string value that is stored in responseText. There is a ticket to finish Ti.Network.HttpClient's implementation here: TIMOB-7151. Part of the problem is that Ti.XML is not 100%. We're not quite sure how far off Ti.XML is from being in parity with the other platforms. I created a ticket for Ti.XML here: TIMOB-7946.
  2. Bryan Hughes 2012-03-10

    Element.text is a non-standard extension to the DOM Level 2 XML implementation (what iOS and Android purport to implement). Mobile Web explicitly follows the DOM Level 2 (technically Level 3) implementation, meaning it doesn't support Element.text. Use Element.textContent instead.
  3. Neeraj Gupta 2012-03-10

    Note that we are documenting this behavior difference (text vs textContent) in the APIDoc.
  4. Kevin Whinnery 2012-03-11

    An API documentation fix is insufficient in this case. People have extensive XML parsing logic in their native apps dependent on the text property. Their logic will not work on mobile web, and they will have no idea why. XML parsing is an API that should achieve 100% parity, there is no justification for having platform-specific differences. I think it should go in 2.0 - if it can't due to time constraints, it should be done ASAP. But this issue can't be closed until API parity is achieved.
  5. Chris Barber 2012-03-11

    I understand, however, the XML parser returns internal document/entity/etc objects. There is no easy or efficient way to "fix" the text property on XML elements. I'm curious why native platforms chose to use "text" instead of "textContent".
  6. Bryan Hughes 2012-03-11

    Kevin: Adding in support for that property will incur a major performance hit on mobile web because we will have to wrap the entire XML API. This will cause major code bloat, thus increasing download size. This will also create multiple additional function call on *every* call to the XML API. The proper solution is to deprecate the .text extension because it is non-standard and support the standards based solution instead. Using the non-standard extensions raises the barrier to entry for web-developers learning our platform, because they are expecting to use the standards based mechanisms. It's always better to say "we support the standard, just use it like you normally do" than to say "we support the standard, but it's not quite the same, so you can't just use it like you normally do." Mobile Web doesn't support any of the properties/methods across the entire API that are currently marked as deprecated...how is this any different? I am *strongly* against adding support for the .text extension.
  7. Kevin Whinnery 2012-03-12

    I understand that wrapping the entire XML DOM API would be a pain in the ass and add to the codebase. But we have to have 100% parity in our XML parsing API, it would be ludicrous to have platform-specific interfaces to a non-visual data processing API. That means that one of the following must happen: 1.) Mobile web has to conform to the existing XML API we have in place 2.) Native has to emulate the XML parsing logic used in a variety of mobile web browsers 3.) We need to settle on a new API that can be implemented uniformly across all platforms Given those options, I think it makes more sense for mobile web to have a defensive wrapper which controls Titanium's XML parsing interface. Having a thin veneer over whatever DOM implementation the browser provides (as in #2) places a rather large burden on native to emulate that browser-specific behavior. But whatever we do, Titanium's XML API should be Titanium's XML API - that's the contract we have with developers. We should define and control that interface. #2 makes no sense - forcing native to emulate browser behavior would be a time-consuming development task, and would still break tens of thousands of native apps. My preference is that we go with something as close as possible to #1, so we don't break, again, the TENS OF THOUSANDS of native applications using XML in 2.0. But if we need to do something closer to #3, then let's get together on that now and message that clearly when the API changes.
  8. Bryan Hughes 2012-03-12

    I still strongly disagree...your arguments are not compelling. 1) will be difficult for us, but that is not why I am against it. It will incur a noticeable performance hit for client applications, and there is simply no way around it if we have to support this one single property. Make no mistake, we will be hurting client apps by doing 1). 2) This is a trivial change for the other platforms (5-minute change). Your claim that "forcing native to emulate browser behavior would be a time-consuming development task" is simply not true. As to breaking tens of thousands of apps, I don't care. Every time we deprecate something, we are breaking apps. I ask again, how is this different than deprecating something else, such as the Geolocation API that has been mostly rewritten? 3) Why would we do this? The *only* difference between Android/iOS and Mobile Web is this one single property that, as previously mentioned, is very easy for them to change.
  9. Chris Barber 2012-03-12

    I agree 110% with Bryan. Developers targeting mobile web can workaround this by simply doing this:
       var item = item.getElementsByTagName(key).item(0);
       Ti.API.log(item.text || item.textContent);
       
  10. Kevin Whinnery 2012-03-12

    I will follow up offline with additional comments, but it seems like having native implement a second property for .textContent, which is the same as .text would be a good "80%" step for 2.0.
  11. Bryan Hughes 2012-03-13

    Element.text is being deprecated in favor of Element.textContent

JSON Source