Wednesday, October 2, 2013

jQuery: NIEM Parsing with jQuery

This series of articles will look at how to leverage jQuery to access and manipulate NIEM-conformant XML payloads. The first article looks simply at the capability to access, parse and read the data contained in a nc:AddressFullText element, strip whitespace from it, and place it in a text area on a web page. Later articles will explain how to handle multiple occurrences of a single element and eventually map the address on a webpage.
jQuery is a powerful scripting tool used by many modern developers in creating and processing web pages. We will be using it as a client-side script where the user's browser is working on an XML stream directly without doing work on a server. This is one approach to leveraging the power of a client's own browser in the current "AJAX" development stagey.
The first step in leveraging jQuery is actually including the appropriate library on your web-page. There are both compressed and uncompressed versions of this library available on jquery.com and in many cases you can simply link to a hosted copy of the library on the web. For this exercise, let's assume we have a copy of the library hosted on the same server (and in the same directory) as the html page we're writing. In this case, we will include the script by using the following:
<!-- jQuery Include (change to match the file name and location where you have the jQuery library stored) -->
<script src="jquery-1.10.2.js"></script>
 
 
With the library included on our HTML page, we can access all the features available to us within our on-page JavaScript. In order to use a stream of XML data, we'll need to first parse it. in jQuery we simply use the $.parseXML(string) command. This will return for us a parsed XML document. As we don't want our users to receive unhandled exceptions, and there is never a guarantee the XML we process is without error, we want to be sure to use try/catch when parsing our file. Here is what the snippet of parsing would look like:
//the try & catch block support for .parseXML() requies jQuery 1.9 or newer!
  try{
       var xmlDoc = $.parseXML(xml);
       var $xml = $(xmlDoc);
     } catch (err) {
       alert("Error parsing XML!  Likely invalid XML or undefined namespace prefix.");
       return;
     }
 
Once we have successfully parsed the XML document, we can access portions of the document using a number of jQuery-supported methods. One of the simplest methods (and the one we will use today) is the xmlDocument.find('pattern') method. It simply returns an element [array] for all the elements it finds that match the pattern passed into the function. For example, if we want to "find" all of the elements called PersonName, we would simply pass it 'PersonName'. Here, we will assume we're working with nc:Address elements that contain plain text addresses and our expanded code will look something like this:
$address = $xml.find("nc\\:AddressFullText, AddressFullText");

You will notice we passed in two parameters. This is to work around a compatibility issue between Web-Kit-Based Browsers (Chrome, Firefox, Safari, etc.) and Microsoft Internet Explorer (IE). IE allows us to use an escape-sequenced colon to define our element prefix (\\:), however the Web-Kit browsers do not. By passing it both a prefixed and simple element name, both browser types will accept and process the find properly.
Since we are processing a plain text field, we will likely have some extra whitespace (spaces and line-feeds) that we don't want. We can simply use a string.replace('pattern') with a regex to clear out what we don't want and save the text value contained in our element by using the .text() method as shown in the following.
//Clear Whitespaces and save text value of the element in a string variable
textAddress = $address.text().replace(/^(\s*)|(\s*)$/g, '').replace(/\s+/g, ' ');
 
Once we have the value saved in a variable, we can now use it in any way we want directly in our script. The following is the full HTML and JavaScript/jQuery code for this example including a text field for entering NIEM-conformant XML and a text field for the parsed data.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>nc:Address jQuery Parse Example</title>

    <!-- jQuery Include (change to match the file name and location where you have the jQuery library stored) -->
    <script src="jquery-1.10.2.js"></script> 

    <!-- On Page JavaScript -->
    <script>
        
        function resolveAddress() {
            var textAddress;
            var $address;
            var xml = textField.value;

            //the try & catch block support for .parseXML() requies jQuery 1.9 or newer!
            try{
                var xmlDoc = $.parseXML(xml);
                var $xml = $(xmlDoc);
            } catch (err) {
                alert("Error parsing XML!  Likely invalid XML or undefined namespace prefix.");
                return;
            }

            //jQuery .find()
            //find any and all values stored in the (possibly repeating) element nc:AddressFullText
            //The following returns an ELEMENT and requires we use .text() to access the return value
            $address = $xml.find("nc\\:AddressFullText, AddressFullText");
            //Clear Whitespaces
            textAddress = $address.text().replace(/^(\s*)|(\s*)$/g, '').replace(/\s+/g, ' ');
            //Output Value
            textFindOutput.value = textAddress;


        }
    </script>

</head>
<body>
    <div>
    <p style="font-family:'Segoe UI'">
        Enter or paste in a valid nc:Address block and click on the "Parse Data" button.
    </p>

    <textarea id="textField" style="width:100%;height:100px">
<myExchange xmlns:nc='http://niem.gov/niem/niem-core/2.0'>
  <nc:Address>
    <nc:AddressFullText>
        One Microsoft Way
        Redmond, WA 98052
    </nc:AddressFullText>
  </nc:Address>
</myExchange>
    </textarea>

    <p><button id="go" onclick="resolveAddress()">Parse Data</button></p>
    </div>
    <div>
        <p style="font-family:'Segoe UI'">jQuery .find("nc\\:AddressFullText") using .text() to access the <u>text</u> found.</p>
        <textarea id="textFindOutput" style="width:100%;height:100px"></textarea>
    </div>

     

</body>
</html>
Additionally, you can simply access a sample of this code working here.

No comments:

Post a Comment