9月教XML课程的时候,使用MSXML来做演示。虽然讲课的时候,我说了不少xml标准的发展,并且说各大厂商将会追随标准不断更新自己的产品。然而事实并非如此。M$就是典型。
MSXML SDK,自毕业论文用过3.0之后,就未再接触过。一直到这次才又捡出来MS XML Core Services 4.0。当前MS最新的XML Parser仍然是发布了很久了的 MSXML 4.0 sp2。我原本以为MSXML 4.0已经支持DOM level 2,但是事实并非如此(相反Mozilla支持了绝大多数DOM2模块以及大量的DOM3特性)。
甚至其对DOM level 1的支持也很令人头大。我写了一段代码,显示一个xml node,一般的,需要根据nodeType来做不同的输出:
switch (node.nodeType)
{
case node.ATTRIBUTE_NODE:
return "{" + node.namespaceURI + "}" + node.nodeName + ": " + node.nodeValue;
break;
case node.TEXT_NODE:
if (node.isElementContentWhitespace) return "";
else return node.nodeValue;
...
}
其中namespaceURI是DOM2增加的prop,但MSXML倒也支持。isElementContentWhitespace是DOM3增加的,用来测试文本节点是否为空(即在源xml中的无意义空白),MSXML不支持,但是由于是js,所以也不影响。但是这段代码仍旧不能按照预期运行(本身这个bug就比较隐蔽,需要拿一个较完整的xmldoc进行测试)。
我费了好大劲调试后才发现,msxml居然没有支持node接口上的常量:XXX_NODE。这样就必须直接写值如下:
switch (node.nodeType)
{
case 2 /*node.ATTRIBUTE_NODE*/:
return "{" + node.namespaceURI + "}" + node.nodeName + ": " + node.nodeValue;
break;
case 3 /*node.TEXT_NODE*/:
if (node.isElementContentWhitespace) return ""; //if (node.nodeValue.match(/^\s*$/)) return "";
else return node.nodeValue;
...
}
显然,用常量的整数值不直观,对程序维护是个问题(虽然可以像上面一样加上注释)。然而,令人郁闷的是,事实上,msxml是有这组常量的:
IXMLDOMNodeType Enumerated Constants
NODE_ELEMENT(1), NODE_ATTRIBUTE(2), NODE_TEXT(3), etc.
问题是:
它不是node接口下的常量;
在动态类型的脚本环境下,没有办法引用由编译器保障的常量名(至少在SDK中没找到example);
它的命名方式跟DOM规范所列常量名不一致!
尤其可恶的是第三点,规范叫做XXX_NODE,M$偏要叫NODE_XXX,不知道M$是出于什么考虑?!微软故意违背标准来嘲笑标准和标准化组织?M$还有个扩展prop叫"nodeTypeString",返回形如'element'、'attribute'、'text'的字符串,但是就偏偏不肯行举手之劳加上标准中Node接口下所列的常量名。并且,在M$及其盟友的世界,我们丧失了自由权利,故我们也无法做任何修正或补救——除了毫无希望的去祈求M$。