Monday, April 28, 2003

The Big Print

264 pages, and all reviewed this weekend. The end is nigh...

Friday, April 25, 2003

Mozilla announces a branding stragegy

Why isn't there some kind of non-profit organization to help open source projects with marketing?


Thursday, April 24, 2003

<micah> I've got a crutch to remember when to use "style sheet" vs. "stylesheet"
<micah> CSS is "style sheet" (otherwise it would be just CS)
<micah> XSLT is "stylesheet" (otherwise it would be XSSLT)


O'Reilly announces Founders' Copyright

This won't apply to XForms Essentials, since the contract is already a done deal, but the GFDL portion will, of course, be there. -m

Monday, April 21, 2003

Mitch Kapor writes: Chandler 0.1 available immediately

With the addition of a parcel to store random bits of text or HTML, plus an XML export, plus a little XSLT, this could be a good client-side replacement for Blogger... -m

Six Reasons why InfoPath is DOA

Richard Tallent.

Then there's this. Hmm. -m

Sunday, April 20, 2003

Also, I'm looking for any pointers to documentation on the funky double-colon JavaScript syntax used in InfoPath.

function XDocument::OnLoad() anyone?

It's obviously some kind of scoping operator. Is it shorthand for something that could be done in a more longhand way? Or is it something completely new? Send mail to mdubinko at, and I'll post the most helpful responses here. -m

XForms and InfoPath maintainability

*Warning* Extreme geekiness ahead.

W3C XForms and InfoPath are heading in opposite directions for now, but there's still some overlap. It's interesting (and somewhat irresistable) to compare the two technologies head to head.

In my book, I have an extended example of an XForms document that creates a UBL purchase order. There are four main computations that happen in the purchase order:

  1. A single currency code is copied into each repeating line item.

  2. Since the currency code appears in two places in each line item, it is copied to the 2nd location

  3. For each line item, the extended price is calculated as price times quantity.

  4. The total of the extended price across all line items is summed up.

Pretty basic stuff, though UBL gets a bit verbose in places. In XForms, this is handled through a four <bind> elements:

<xforms:bind nodeset="cat:OrderLine/cat:LineExtensionAmount/@currencyID"
<xforms:bind nodeset="cat:OrderLine/cat:Item/cat:BasePrice/cat:PriceAmount/@currencyID"
<xforms:bind nodeset="cat:OrderLine/cat:LineExtensionAmount" type="xsd:decimal"
calculate="../cat:Quantity * ../cat:Item/cat:BasePrice/cat:PriceAmount"/>
<xforms:bind nodeset="cat:LineExtensionTotalAmount" type="xsd:decimal"

In InfoPath, as far as I can tell, raw script is needed to access the DOM nodes and perform operations there. (At least, all the samples I've seen do this.) The equivalent script for the InfoPath object model is this:


function XDocument::OnLoad(eventObj)

// This function is associated with: /ns1:Order/cat:OrderLine/cat:Quantity
function msoxd_cat_Quantity::OnAfterChange(eventObj)

// This function is associated with: /ns1:Order/cat:OrderLine/cat:Item/cat:BasePrice/cat:PriceAmount
function msoxd_cat_PriceAmount::OnAfterChange(eventObj)

// This function is associated with: /ns1:Order/cat:LineExtensionTotalAmount/@currencyID
function msoxd__LineExtensionTotalAmount_currencyID_attr::OnAfterChange(eventObj)

function recalcLineItem( lineNode ) {
var quantity = lineNode.selectSingleNode("cat:Quantity");
var price = lineNode.selectSingleNode("cat:Item/cat:BasePrice/cat:PriceAmount");
var extended = lineNode.selectSingleNode("cat:LineExtensionAmount");
var extPrice = parseFloat(getElementValue(quantity)) * parseFloat(getElementValue(price));

setElementValue(extended , floatToString(extPrice, 2));

function recalcTotal() {
var dom = XDocument.DOM;
var extended = dom.selectSingleNode("/ns1:Order/cat:LineExtensionTotalAmount");
var newTotal = sum("/ns1:Order/cat:OrderLine/cat:LineExtensionAmount");
setElementValue( extended, newTotal );

function updateCurrency() {
var dom = XDocument.DOM;
var copyFrom = dom.selectSingleNode("/ns1:Order/cat:LineExtensionTotalAmount/@currencyID");
var lines = dom.selectNodes("/ns1:Order/cat:OrderLine");

// loop through each line item, copying in the currencyID
for (var idx=0; idx<lines.length; idx++) {
var copyTo = lines[idx].selectSingleNode("cat:LineExtensionAmount/@currencyID");
copyTo.nodeValue = copyFrom.nodeValue;
copyTo = lines[idx].selectSingleNode("cat:Item/cat:BasePrice/cat:PriceAmount/@currencyID");
copyTo.nodeValue = copyFrom.nodeValue;

// Utility functions

function getElementValue( node ) {
if (node.firstChild)
return node.firstChild.nodeValue;
return "";

function setElementValue( node, newval ) {
if (node.firstChild) {
node.firstChild.nodeValue = newval;
} else {
var textnode = node.ownerDocument.createTextNode( newval );
node.appendChild( textnode );

function sum(xpath) {
var nodes = XDocument.DOM.selectNodes(xpath);
var total = 0;
for (var idx=0; idx<nodes.length; idx++) {
total = total + parseFloat(getElementValue(nodes[idx]));
return total;

function floatToString(value)
return "" + value;

I am obviously biased, but this seems a bit excessive. Even simple things like getting or setting a value from an element node require significant care. Even with the excellent script debugger that comes bundled, it took me most of a day to get this working.

Conclusion: neither XForms nor InfoPath have been around long enough to gather any useful metrics on maintainability. The declarative approach of XForms, however, seems to have the advantage.


Thursday, April 17, 2003

CSS syntax for N-Triples

One way to deal with RDF in HTML is to use a compact syntax that can live in <script>, <style>, or possibly some new element in the head of an XHTML document.

Raw N-Triples could work, except that it's too verbose for most hand authors, and the pesky angle brackets would need to be escaped.

A CSS syntax would solve these problems. Let's compare:


A discussion of the broader context and relevance of XML/RDF techniques.
<dc:creator>Uche Ogbuji</dc:creator>


<> <>
"A discussion of the broader context and relevance of XML/RDF techniques." .
<> <>
"Uche Ogbuji" .


@namespace dc url(

:root {
dc|description: "A discussion of the broader context and relevance of XML/RDF techniques.";
dc|creator: "Uche Ogbuji";

Note that the CSS3 :root selector is used to make a 'this here document' self-reference. To make assertions about other URIs, you could either use the url() function as a selector, or select an element that points off to some URI.

Some will argue that the last thing RDF needs is another syntax. Yet, none of the existing ones are workable within DTD-valid XHTML, it seems. Re-using CSS parsing technology seems like a good compromise. Maybe.



Monday, April 14, 2003

Do not go where the path may lead;
go instead where there is no path and leave a trail.

-- Ralph Waldo Emerson

Saturday, April 12, 2003

Book update:

(nearly) all of the @@@ are gone.


Friday, April 11, 2003

Tips for the Outlook built-in Junk Mail filters

In Outlook 2000, you can right-click on a message and choose Junk Mail -> Add to Junk Senders list. (Unfortunately, this only works on a per-message basis...more pain when you have 100 spam in the morning)

All such blacklisted addresses are kept one-per-line in the file at <documents and settings>\<username>\Application Data\Microsoft\Outlook\Junk Senders.txt

For all newly-arrived messages, Outlook checks to see whether the "From:" text includes any of the blacklisted strings. Note that it's a case-insensitive substring search, so for example if the blacklist contains "BR", then all messages from will get flagged.

In fact, this happened to me, after some joker sent me spam with a from of "BR". Even worse, I got one with a return address of ".", which caused everything to get sent to the spam folder. (Outlook hides the actual return address in most cases, so you can't even see what you're adding to the list.)

It's good to periodically go through the text file with a sufficiently capable editor, doing a regex search for ^.{1,5}$ to weed out any short lines that end up there.

Even better, run SpamAssassin along with the built-in filters. -m

XForms and the Real World

Sorry, no new reality show, just a response to Gerald Bauer's recent presentation and subsequent message on www-forms.

The presentation was of the kind that covers several topics, briefly mentioning plusses and minuses on each. On XForms, he praised the separation of content from controls, the XML-in-XML-out philosophy, and the increased functionality. Most of his criticisms seem strained.

Whatch your language - plain-English, please; no academese or jaron-filled mumbo jumbo (example) trigger -- what's wrong with button?

Hmm, "trigger" seems quite short and descriptive for something more general than a "button"; think of a voice activated control, or even an ordinary hyperlink. For the prose, the target audience for a specification is implementers, who demand precise language. If you're looking for an end-user guide, then find a good book. :-)

Markup bloat; don't overdo tags; allow attribute shortcuts

This isn't black and white. There are serious internationalization problems with readable text in attributes, and even proposals to make things more elemental.

XML fever; don't replace scripting with bloated markup

Remove the subjective word 'bloated', then ask Why Not?

Drop namespaces; ditch the useless bloat from core markup

Namespaces suck, but they're now a permanent fixture. Maybe XML 2.0 will be better.

Incendentally, a legitimate complaint would be that it's currently hard to craft CSS attached to XForms that provides a good rendering across the 5 major implementations. Another is that more work is needed on integration with SVG and XHTML.

His forum message concludes

please don't wait for miracles as Microsoft,
IBM, Adobe

I don't know where he got the recurring idea that anyone was waiting. But for those that might be, IBM just announced a number of client and server implementaions, and an excellent plug-in for IE is available. -m

Saturday, April 05, 2003

Outlook: Pain

I've installed SpamAssassin under Win32, following these excellent instructions. Remarkable piece of software.

Next task: since I don't control any mail servers, get it running on the client Outlook 2000. (my work email address appears in a few conspicuous places, and I get plenty o' spam) The page above has some VBScript to call from the "NewMail" entry point, and an even more recent version at SourceForge. But it is VB, and it is a wonderful, terrible hack.

Basically, it writes the email message to disk (including some incredible contortions to get to the headers), spawns off a batch file that runs Perl and SpamAssassin, then reads the newly created result file and looks for the "X-Spam-Flag: YES" header.

Outlook makes this much more painful than it already is. First of all, the Application_NewMail entry point stupidly doesn't include any way to tell what the actual new message or messages are. Worse, it can't reliably read or write temp files. Read failures allow spam to get through, which is annoying. Write failures cause the top message in the inbox to be treated like the *previous*, still-in-the-temp-folder, message, which is catastrophic when an important message comes in just after spam.

I guess the solution is to never reuse a file name for the temp file, maybe include the date or something. Back to hacking...

Tuesday, April 01, 2003

...Influential standards architect Jim Lerners-Lee had this to say: "I hate all this newfangled crap. XHTML2, XFORMS, CSS3. It's all so complicated. Me, I like tables. Good old-fashioned tables. Especially when used with the blink tag."

Somebody needs to tell Jim there that it's "XForms", not "XFORMS". Whew, glad I got that off my chest.


Timothy Dyck of eWeek favorably compares XForms to InfoPath. -m


Terms of use

For external use only. I doubt the enforcability of click-through licenses anyway. Copyright 2003 Micah Dubinko. All rights reserved.