Common JavaScript and XML Mistakes

Common errors that catch developers out when creating JavaScript + XML scripts

Including the Root Element

This is a very common mistake when creating JavaScript to access XML content. Consider the following:

var myXml = <order>
  <customer>
    <firstname>John</firstname>
    <lastname>Smith</lastname>
  </customer>
  <item>
    <description>LCD Television</description>
    <price>1299.99</price>
    <quantity>1</quantity>
  </item>
</order>

To access the firstname element content, use

myXml.customer.firstname
i.e. the access path is relative to the root element and therefore the root element should NOT be included. This is a common gotcha when attempting to access and manipulate XML using JavaScript. Using
myXml.order.customer.firstname
will return an empty result as there is no <order> element under the <order> root.

 

Assigning Values Between XMLObjects

This is a typical mistake when creating JavaScript to manipulate XML content. Consider two very simple XML objects:
var address = <address><firstname>Peter</firstname></address>;
var order = <order><reference></reference></order>;
We wish to set the value of the order reference i.e. order.reference to the firstname within the address object i.e. address.firstname. Using the following
order.reference = address.firstname;
Results in a somewhat unexpected outcome – the order variable now becomes:
<order>
  <firstname>Peter</firstname>
</order>
Instead of the order.reference value being set, the element is instead replaced by the firstname element. To perform the assignment correctly, use the text() operator to obtain the firstname element content i.e.
order.reference = address.firstname.text();

Namespace Prefixing

An absolutely vital, though often overlooked, aspect of creating code to access XML elements or attributes using JavaScript is to ensure that the correct namespace prefixes are used appropriately. The Rhino E4X environment is namespace-aware. For example, the elementFormDefault attribute for the types schema within the GlobalWeather Service is set to true. Therefore all elements must be qualified accordingly. The correct SOAP content for a searchByCountry request is shown below:
var xsd1 = 
  new Namespace('http://www.capeclear.com/globalweather/xsd/');
var soapenv = 
  new Namespace('http://schemas.xmlsoap.org/soap/envelope/');

var searchByCountry = <?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope
    xmlns:xsd1="http://www.capeclear.com/globalweather/xsd/" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsd='http://www.w3.org/2001/XMLSchema'
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
    <soapenv:Body>
        <xsd1:searchByCountry>
            <xsd1:country>France
        </xsd1:searchByCountry>
    </soapenv:Body>
</soapenv:Envelope>
Using the following to set the value of the country element will result in the creation of an illegal (unqualified) country element i.e.
searchByCountry.soapenv::Body.xsd1::searchByCountry.country = "France";
Results in:
<soapenv:Envelope 
xmlns:xsd1="http://www.capeclear.com/globalweather/xsd/" 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <xsd1:searchByCountry>
      <xsd1:country>France
      <country>France
    </xsd1:searchByCountry>
  </soapenv:Body>
</soapenv:Envelope>
As the correct prefix was not used, an additional country element has been added rather than the content of an existing element being replaced. The correct JavaScript, with prefixes set properly is:
searchByCountry.soapenv::Body.xsd1::searchByCountry.xsd1::country = "France";