Firefox hides the ?xml processing instruction

When I was testing the DOM handling of the XML processing instructions in various browsers, I've found an interesting inconsistency: Internet Explorer includes the <?xml ?> processing instruction in the DOM tree, while Firefox hides it.

For example, when the following XML document ...
<?xml version="1.0" encoding="windows-1250"?>

<?xml-stylesheet href="countryPage.xsl" type="text/xsl"?>

<Test />
... is transformed into a DOM tree and processed with this JavaScript function:
function testPI(dom) {

var topNodes = dom.childNodes;

for (var i = 0; i < topNodes.length; i++) {

var node = topNodes[i];

wr("nodeType="+node.nodeType);

if (node.nodeType == 7) {

wr("PI="+node.target+" ... "+node.data);

}

}
... Internet Explorer generates the following text:
nodeType=7
PI=xml ... version="1.0" encoding="windows-1250"
nodeType=7
PI=xml-stylesheet ... href="countryPage.xsl" type="text/xsl"
nodeType=1
... while Firefox skips the <?xml ?> processing instruction:
nodeType=7
PI=xml-stylesheet ... href="countryPage.xsl" type="text/xsl"
nodeType=1


IP address to physical location mapping

On every web site where I can configure the web server parameters (sadly not available in all hosting environments), I catch the ASP errors (500;100 error page), acknowledge them to the web user and report them in an e-mail to the webmaster (if you can't debug every possible code path, it makes sense to fix the bugs once the first visitor hits them).

Sometimes I would also like to figure out where the visitor causing the ASP error is coming from (more so if the errors are due to lack of resources, indicating unexpectedly high load). The usual tools (nslookup) fail if the ISPs don't enter their IP address space in reverse DNS lookup zones. In the past I've tried to use various Internet registries to figure out who the address is allocated to … and finally I've stumbled on the IP2Location web site, which does exactly what I was looking for: I enter the IP address and it tells me where the visitor is coming from (including a nice overview map for those who have no clue about geography).

Publish code samples in Blogger

Publishing the code samples in Blogger has always been a pain in the ***: the quoting of angle brackets doesn't work very well unless you do it manually, the leading whitespaces get lost (more so if you use spell checker), the line breaks are sometimes lost as well ... Finally I gave up and wrote a small PERL script that takes your code on standard input (usually supplied as a file name in the command line) and leaves the Blogger-ready markup on the clipboard, ready to be inserted in your post:
use strict;
use Win32::Clipboard;

our $lcnt = 0;
our $result = "" ;
our $CLIP = Win32::Clipboard();

while (<>) {
  if (/\n/) { chop; }
  $_ =~ s/\&/&amp;/gi;
  $_ =~ s/\</&lt;/gi;
  $_ =~ s/\>/&gt;/gi;
  while (/^\s/) { $_ =~ s/^(\s*)\s/$1&nbsp;/gi; }
  $result .= ($lcnt == 0 ? "<pre class='code'>" : "\n") ;
  $result .= $_;
  $lcnt ++;
}
$result .= "</pre>";
$CLIP -> Empty();
$CLIP -> Set($result);
print "Result is on the clipboard";

If you're not fluent in PERL, don't even try to understand what it does ... it works :)

Extract the default stylesheet from the DOM document

If you use XSLT transformations to change the XML data into HTML markup and use the xml-stylesheet processing instruction to specify the default XSLT stylesheet to use for the transform, you might need to fetch the default stylesheet value in JavaScript when developing AJAX applications.

You can find a good case study on using XML and XSLT in my Inform-IT article Optimized Presentation of XML Content.


The following JavaScript function extracts the default XSLT stylesheet from the XML document (passed to the function as DOM Document object). It relies on the fact that the DOM Document object extends the Node object and thus has the childNodes property that contains the root element as well as all processing instructions.

function getXMLStylesheet(dom) {

var topNodes = dom.childNodes;

for (var i = 0; i < topNodes.length; i++) {

var node = topNodes[i];

if (node.nodeType == 7) {

if (node.target == "xml-stylesheet") {

var match = /href="(.*?)"/gi.exec(node.data);

if (match.index >= 0) return match[1];

}

}

}

}


A typical usage of this function is illustrated below:
<script src="/sarissa.js"></script>

...

<script>

var xrq = new XMLHttpRequest();

xrq.open("GET","getPI.xml",false);

xrq.send(null);

if (xrq.status == 200) {

var dom = xrq.responseXML;

var xsl = getXMLStylesheet(dom);

alert("stylesheet="+xsl);

}


Constants of the DOM Node object are not implemented in Internet Explorer

The DOM Node object defines a set of constants that can be used to identify the node type. These constants are available in Firefox (and, I would assume, all other Gecko-based browsers), but not in the Internet Explorer. The expression ...

if (node.nodeType == node.TEXT_NODE) { ... }

... which would be largely self-documenting thus has to be written as ...

if (node.nodeType == 3) { ... }

... unless you define the same constants in your JavaScript.

Use JavaScript Progressive Enhancement to simplify HTML table formatting

In the Enrich Your HTML Tables with JavaScript Progressive Enhancement article I wrote for InformIT.com, I'm describing how you can use JavaScript progressive enhancement techniques to add last touches to your HTML table format after the web page has been loaded into the web browser ... and, no, I'm not talking about page layout with tables :), I'm talking about formatting data that deserve tabular format.

Should I encode data as XML attributes or child nodes

This question pops up quite commonly: should I encode my AJAX data as XML attributes or as child tags with actual value in the text of the tag? The answer, as always, depends on your data structure:
  • If your data is simple and non-hierarchical (for example, results of SQL query), using XML attributes will reduce the response size (due to shorter markup)
  • If you have repeating values in your data set, you cannot use attributes, as XML allows only a single attribute with a certain name per tag. In this case, you have to use child tags to encode repeating values. However, you can still transfer the actual value as an attribute of the child tag, not as text in the tag.
  • If you're transfering large character fields, using child tags will increase the readability of the XML response when you're inspecting it with a browser (you know, sometimes we have to do a bit of debugging :)
  • You might hit platform-dependent limitations if you use long attribute values, so yet again you would be better off using child nodes in this case
  • Obviously, you cannot use CDATA section in an attribute, the attribute value has to be properly quoted.

This post is part of You've asked for it series of articles.

How do I use xsl:choose

The Google query strings bringing visitors to my blog are sometimes amazing, like the one in the title of this post. Let's start with a tangential remark: if you're serious about XSLT, you should invest into a good book (XSLT Programmer's Reference is one of the best technical books I've ever read). If, on the other hand, you're just looking for a quick fix, here's the whole story

XSLT does not have if-then-else or select-case constructs like most other languages. You can implement both functions with the xsl:choose element that can take as many xsl:when children as needed. These are evaluated sequentially, the first one that succeeds is executed. You can also use xsl:otherwise as the last child in the list to specify the default behavior.


This post is part of You've asked for it series of articles.