XML Support in Internet Explorer

Internet Explorer versions 5.0 and later provide good support for XML on the client. Among the supported features are direct browsing and data islands. Direct browsing is the browser’s ability to automatically apply an Extensible Stylesheet Language Transformation (XSLT) to the XML files being viewed. In particular, Internet Explorer uses a default, built-in style sheet unless the document points to a specific style sheet. The default style sheet produces the typical tree-based view of nodes you’re familiar with. If, as mentioned in Chapter 7, the XML document includes its own style sheet reference (the xml-stylesheet processing instruction), the direct browsing function automatically applies the style sheet and displays the resulting HTML code.

A data island is an XML document that exists within an HTML page. In general, a data island can contain any kind of text, not just XML text. Since version 5.0, Internet Explorer provides extra support for XML data islands. If you use the special <xml> tag to wrap the text, the browser automatically exposes the contents as an XML Document Object Model (XML DOM) object and allows you to script against the document. The XML DOM object is expressed as a COM object created by the MSXML parser. The advantage for developers is that the XML data travels with the rest of the page and doesn’t have to be loaded using ad hoc script or through the <object> tag. On the other hand, because the XML data is an integral part of the page, the size of the page itself grows. Determining the best way to include XML data for client-side processing is application-specific, but the <xml> tag certainly represents an interesting and compelling option.

The Data Island (<xml>) Tag

The <xml> tag marks the beginning of a data island, and the ID attribute provides the name you use to reference the XML DOM object. The XML text can be inserted in the data island either in-line or through an external reference to a URL. The following code snippet shows an XML data island with in-line text:

<html>
<xml id="xmldoc">
<Employees>
  <Employee ID="1">
    <LastName>Davolio</LastName>
    <FirstName>Nancy</FirstName>
  </Employee>
</Employees>
</xml>
</html>

The <xml> tag simply wraps the XML data; it is not part of the data. Internet Explorer does not throw an exception if the XML text is not well-formed, but if the XML data is not well-formed, the MSXML parser fails to load it, and no XML DOM object is made available to client-side scripts.

The following code snippet demonstrates the use of the src attribute with the <xml> tag. If this attribute is specified, the XML data and the host page from the specified URL are downloaded separately.

<html>
<xml id="xmldoc" src="EmployeesData.xml" />
</html>

The contents of the XML data island are not displayed as a portion of the page. This means that if you attempt to view any of the preceding HTML pages using Internet Explorer, an empty page will be displayed. In fact, the pages have no contents other than the data island.

Note

The XML data island should not include a nested <xml> tag. If this happens, no error is returned, but the nested end tag </xml> closes the data island’s open <xml> tag. As a result, the XML text that follows the nested <xml> element becomes part of the HTML body and is treated as displayable contents.


The Role of the MSXML Parser

Internet Explorer uses the COM-based MSXML parser to load the contents of the XML data island into a programmable XML DOM object. The parser is included in the Internet Explorer installation, so for this feature to work, you don’t have to install an additional tool. Of course, the availability of a client-side XML parser is a necessary condition for handling XML data on the client.

In the next section, we’ll review alternative ways to embed nondisplayable XML data in HTML pages. Some of these tricks also work with Internet Explorer 4.0 and old Netscape browsers. Bear in mind, however, that although you can figure out several ways to embed XML data in HTML pages, you always need a client-side, script-accessible XML parser to consume that data effectively. COM objects and Java classes are probably the most popular and broadly available tools to process client-side XML. In this chapter, we’ll look at a third approach that requires the availability of the .NET Framework.

Accessing Data Islands Through Script

Let’s expand the previously created HTML pages with some script code to see what’s needed to programmatically access the embedded XML data island. The following HTML page contains a button that, when clicked, prompts you with the XML contents of the data island:

<html>
<xml ID="xmldoc">
<Employees>
<Employee ID="1">
  <LastName>Davolio</LastName>
  <FirstName>Nancy</FirstName>
</Employee>
</Employees>
</xml>

<script language="javascript">
function getDataIsland() {
    alert(xmldoc.XMLDocument.xml);
}
</script>

<body>
<input type="button" value="Outer XML" onclick="getDataIsland()">
</body>
</html>

Figure 14-1 shows the page in action.

Figure 14-1. Extracting and displaying the contents of the XML data island.


As mentioned, when Internet Explorer encounters the <xml> tag, it extracts the XML data and initializes an XMLDOMDocument COM object. The object is created and returned by an internal instance of the MSXML parser. Internet Explorer calls the loadXML method on the parser and initializes the XML DOM object using the data island contents. The document instance is then added to the HTML object model and made available to scripts via the document.all collection, as shown here:

var doc = document.all("xmldoc");

The document.all property is a name/value collection that contains all the elements found in the HTML page. To simplify coding, Internet Explorer also provides an object instance named as the ID of the data island. The data island contents can be referenced using either the document.all collection or the property with the same name as the ID.

Once you hold the reference to the data island, you use the XMLDocument property to access the actual contents, as shown here:

var dataIslandText = xmldoc.XMLDocument.xml;

This expression demonstrates how to access the entire XML text stored in the data island. If you need to access a subset of the XML DOM object, you can narrow the set of nodes by using an XPath query or by moving to a particular root node.

Handling Parsing Errors

If errors occur during the parsing of the data island contents, Internet Explorer does not raise exceptions; any error is silently trapped and a null object is returned. The code shown in the previous section for accessing the data island does not produce run-time errors in the case of badly formed XML text, but an empty string is returned. To check for errors, use the parseError property of the XMLDOMDocument object.

The parseError property is a reference to an XMLDOMParseError object. The XMLDOMParseError object returns information about the last parser error. This information includes the error number, line number, character position, and a text description.

The following code shows a version of the script code from the previous section modified to provide error handling:

<script language="javascript">
function getDataIsland()
{
    if(xmldoc.parseError.errorCode == 0)
        alert(xmldoc.XMLDocument.xml);
    else
        alert("ERROR: " + xmldoc.parseError.reason);
}
</script>

Note

All the code we’ve looked at up to now as part of a static HTML page can be dynamically generated by Active Server Pages (ASP) or Microsoft ASP.NET code. Later in this chapter, in the section “Creating Data Islands in ASP.NET,” on page 603, we’ll examine ASP.NET pages that produce HTML code with child XML data islands.


Other Ways to Embed XML Data

The main reason for embedding XML data in a special tag is that an XML document is formed by a sequence of markup delimiters that in most cases are unrecognized by a Web browser. By using a special tag like the <xml> tag, you instruct the browser to treat the embedded information in an appropriate way. Note that although an XML data island is a general concept, the <xml> special tag is a peculiarity of Internet Explorer versions 5.0 and later. Other browsers, including older versions of Internet Explorer, don’t support the <xml> tag and don’t provide alternative specific tags.

Normally, Web browsers ignore any tag they encounter that is not part of the predefined HTML vocabulary. Most browsers don’t raise errors; instead, they send all the text found between the start and end tags in the main body of the page. Consider the following HTML page:

<html>
<body>
<specialtext>Hello, world</specialtext>
</body>
</html>

This page produces the following output when viewed with Internet Explorer 5.0 and Netscape Communicator 4.5 and later versions. Neither browser recognizes the <specialtext> tag; they simply ignore the tag and inject the inner text in the body.

Hello, world

Data islands let you embed external blocks of data so that they have no impact on the final page being rendered but are accessible programmatically. In other words, the contents of a data island must be invisible to the user but not to the other child components of the page.

Let’s look briefly at how to simulate data islands with Internet Explorer 4.0 and older HTML 3.2 browsers such as Netscape 4.x. This information will be useful if you create ASP.NET pages with embedded islands of data that can be viewed through a variety of browsers.

Data Islands in Internet Explorer 4.0

Internet Explorer 4.0 already provides great support for Dynamic HTML (DHTML). For our purposes, this means that once you’ve assigned an ID to a tag, you can later retrieve the tag by name and run a script against it. Internet Explorer 4.0 also provides good support for cascading style sheets (CSS), which means that you can use ad hoc attributes to control the visibility style of any tag you want.

If you plan to embed XML text in an HTML page using an ordinary tag, keeping the text invisible is only half the task. The key is forcing the browser not to process the embedded text as HTML. In Internet Explorer 4.0, the <pre> tag is one of few that offers this capability. When you combine display styles and implicit ID-based object references, you can write code similar to the following:

<pre id="xmldoc" style="display:none">
  <xmldata>XML data island</xmldata>
</pre>

You wrap the XML code in any HTML or custom tag you want, making sure to assign it a unique ID and set the CSS display attribute to none. As a result, the contents of the XML data island will be accessible through the expression shown here and, more important, won’t affect the page rendering:

xmldoc.innerHTML

What you get using this technique is not an XML DOM object, however, but a plain string. Initializing a valid XML DOM object and actually parsing and manipulating the XML contents is completely up to you.

Using Hidden Fields

HTML 3.2–compliant browsers make things slightly more difficult. You can’t count on CSS support, and you can’t expect to find a rich object model attached to all tags. A good compromise can be assigning the XML source code to an INPUT control marked as hidden, as shown here:

<form>
<input name="xml" type="hidden" value="XML code">
</form>

Assigning a name attribute to the INPUT tag lets you retrieve the XML code later through the following code:

oForm = document.forms[0];
oInput = oForm["xml"];
alert(oInput.value);

Be sure to use the exact case for names, and be sure to wrap the INPUT tag in a FORM tag. Both things arent’t necessary with Internet Explorer, but Netscape’s browsers require it.

Note

In general, you can name the outer form as well and use the name to select the particular form that contains the hidden field. However, bear in mind that if you use this technique from within ASP.NET pages, only one form is available.


The <script> Tag

Another possible trick for embedding XML data in an HTML page entails using the <script> tag. There are two possible ways of overloading the <script> element so that it accepts XML contents. The approaches differ in the trick they use to inform the <script> tag that it is actually handling XML data.

You can use the language or the type attribute. Set the language attribute to xml, or set the type attribute to text/xml, as shown in the following code:

<script type="text/xml" id="xmldoc1">
    XML content here
</script>
<script language="xml" id="xmldoc2">
    XML content here 
</script>

You can also reference the XML data through the src attribute by making the attribute point to an external URL, as shown here:

<script language="xml" src="EmployeesData.xml"></script>

In all these cases, you should give the tag a unique ID and use it to access the XML data either directly or through the document.all collection.

Note

Overall, if you can control the version of the client browser, the <xml> tag is by far the most preferable and flexible solution. Otherwise, I suggest that you embed any XML data in a hidden field.


Creating Data Islands in ASP.NET

To create data islands in ASP.NET, you can use the <asp:xml> server control to inject XML code in the body of the HTML <xml> tag. We saw this technique in action in Chapter 7 when we examined XSLT and used the <asp:xml> control to apply server-side transformations. The <asp:xml> control can also be used to inject plain XML code without any preliminary transformation.

The following code demonstrates an ASP.NET page that is functionally equivalent to the HTML page discussed in the previous section. The page creates a couple of data islands by importing the contents of a local XML file and then using a hidden field. The page contains two buttons bound to client-side scripting to read the XML source.

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml.Xsl" %>

<script runat="server">
void Page_Load(object sender, EventArgs e)
{
    button1.Attributes["onclick"] = "getDataFromXmlTag()";
    button2.Attributes["onclick"] = "getDataFromHiddenField()";
    RegisterHiddenField("xml", "<xmldata>my data</xmldata>"); 
}
</script> 

<html>

<script language="javascript">
function getDataFromXmlTag() {
    // Get the data island content from the IE5+ <xml> tag
    if(xmldoc.parseError.errorCode == 0)
        alert(xmldoc.XMLDocument.xml);
    else
        alert("ERROR: " + xmldoc.parseError.reason);
}

function getDataFromHiddenField() {
    // Get the data island content from a hidden field
    oForm = document.forms[0];
    oInput = oForm["xml"];
    alert(oInput.value);
}
</script>

<body>
<h1>Creating Data Islands</h1>

<!-- Client-side XML data island -->
<xml id="xmldoc">
  <asp:xml runat="server" documentsource="employees.xml" />
</xml>
<!-- End of the data island -->

<form runat="server">
  <asp:button runat="server" id="button1"
    text="From <xml> tag..." />
  <asp:button runat="server" id="button2"
    text="From hidden field..." />
</form>

</body>
</html>

To create a hidden field, you can use the plain INPUT HTML tag with the type attribute set to the hidden keyword. In ASP.NET, however, you can also use the new RegisterHiddenField method exposed by the Page object. The advantage of this technique is that you can create and add the field dynamically. The following code shows how it works:

RegisterHiddenField("xml", "<xmldata>my data</xmldata>");

The method takes two arguments: the unique name of the input field and the contents to be output. When the method executes, no actual HTML code is generated, but a reference is added to an internal collection to keep track of the hidden fields to be created. The hidden input field is actually added to the output when the HTML code for the page is rendered.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.81.210