XML数据查看器的设计与实现

在本文中,将探讨一个基于MVC(Model-View-Controller)架构的XML数据查看器的设计与实现。这个查看器使用JavaScriptDOM(Document Object Model)来解析和展示XML数据。为了更好地理解本文,建议先阅读有关使用Internet Explorer作为脚本GUI的文章,以及了解如何在JScript中读取二进制文件的背景知识。此外,本文也会涉及AJAX的相关内容。

Exsead的核心概念

Exsead的核心概念在这里被介绍。为了从本文中获得最大的收益,最好已经阅读了有关使用Internet Explorer作为脚本GUI的文章。本文的代码也利用了作者的JScript读取二进制文件的系统,该系统在这里有详细描述。本文使用的AJAX背景信息在这里。

XMLViewer.js脚本介绍

代码示例中包含了XMLViewer.js脚本,该脚本使用MVC概念来构建一个简单但有效的XML数据查看器。还包括了一个更简单的MVC示例(来自之前关于使用Internet Explorer作为GUI的文章),它被称为MVCExample.js。任何像这样解析XML的脚本的目的是将存储在XML中的原始数据转换为可用的知识。XML本身是完全静态的数据,没有用处;它必须被解析到程序中才能“活起来”。这正是XMLViewer.js所做的。

XMLViewer.js的结构

XMLViewer.js是一个相当长的脚本,因为它执行了几个不同的功能来达到其目标。然而,整体结构非常简单;各部分如下:

  • ProcessArguments:这个函数处理传递给脚本的参数,如果没有传递参数,则采取默认操作。
  • DisplayXML:正如它所说的,它将XML的视觉表示推送到Internet Exporter GUI。
  • XMLClean:这只是一个简单的实用程序,用于从文本中转义<符号。
  • ProcessNode:正如稍后将看到的,XML存储为节点树,这个函数由DisplayXML用来遍历整个树,创建XML结构的HTML表示,边遍历边创建。
  • GUIWindow:这是一个对象函数,即创建一个对象的函数。它创建的对象是Internet Explorer实例的包装器。然后可以使用该类作为DisplayXML用来将XML的视觉(HTML)表示发送到Internet Explorer的方法。
  • BinaryFile:作为另一个对象函数,它创建BinaryFile对象,允许JScript以二进制而非文本的方式读取和写入文件。它用于读取XML文件。
  • ConcatStringArray:这是一个非常实用的工具,它接受一个字符串数组,并返回通过连接它们创建的字符串。这比简单地添加大量的字符串要快得多,尤其是当字符串开始变长时。

处理参数

如果向脚本传递参数,这正是当将XML文件拖放到脚本图标上时发生的情况,这个函数将作为二进制文件读取该文件,然后将内容传递给DisplayXML。如果没有参数,则ProcessArguments使用AJAX从Nerds-Central ATOM feed获取XML数据流,并将返回的XML传递给DisplayXML。

JavaScript代码示例

以下是处理参数和文件读取部分的JavaScript代码示例:

for (var i = 0; i < WScript.arguments.count(); ++i) { var chunks; var fn = WScript.arguments.item(i); var bf1 = new BinaryFile(fn); var xml = bf1.ReadAll(); DisplayXML(xml); }

以下是AJAX部分的JavaScript代码示例:

var ajax = WScript.CreateObject('Microsoft.XMLHTTP'); for (var i = 0; i < 32; ++i) { try { ajax.open('GET', 'http://nerds-central.blogspot.com/feeds/posts/default', false); ajax.setRequestHeader('Connection', 'close'); ajax.send(); if (!ajax.status == 200) throw ('Got Wrong Status:' + ajax.status); break; } catch (e) { for (var a in e) { WScript.Echo(a + ' = ' + e[a]); } WScript.echo('Failed to get atom feed from Nerds-Central: tries left=' + (32 - i)); } } if (i != 32) DisplayXML(ajax.responseText);

DisplayXML函数

给定一个XML字符串,这个函数使用Microsoft DOM解析器来解析它。然后它定位DOM的文档部分(DOM - 文档对象模型 - 除了文档本身还有其他部分)。

var xmlDOM = new ActiveXObject("Microsoft.XMLDOM"); xmlDOM.loadXML(xml); var doc = xmlDOM.documentElement;

一旦它有了文档元素,它就创建一个数组,该数组将用于存储所有的输出HTML。这种方法被采用是因为新的HTML片段可以非常高效地“推送”到数组的末尾,然后整个数组在最后一刻被转换为字符串。

理解DOM概念

要理解下一个谜题的片段,必须理解DOM概念是如何模拟XML的。像大多数现代软件概念一样,它实际上比许多人希望相信的要简单得多!在处理XML时,有两个核心概念需要理解:

  • 一切都是节点。
  • 忽略不需要担心的一切。

节点实际上只是简单的容器。它们可以包含其他节点,或者可以包含文本。所以像这样的XML片段:

<myParent><myChild>Hello World</myChild></myParent>

将在DOM中存储为3个节点。第一个节点将有nodeName为myParent。它将有一个子节点,该子节点将有nodeName为myChild。myChild节点也将有一个子节点。但这个子节点没有名称。然而,它包含文本。它有一个nodeValue为Hello World。

ProcessNode函数

ProcessNode函数接受一个节点,并生成该节点及其所有后代的HTML表示。所以DisplayXML将文档元素(为什么它不被称为文档节点 - 不知道)传递给ProcessNode。

ProcessNode是一个“递归下降处理器”。听起来非常复杂,令人困惑和可怕... 但再次,它实际上相当简单。推理过程是这样的:每个节点要么有值,要么有子节点。有一个函数并处理一个父节点。一个父节点就像一个子节点一样。所以,使用同一个函数来处理父节点及其子节点。这样做的最简单的方法是让处理父节点的函数调用自身来处理每个子节点。一个调用自身的函数称为递归函数。一个使用递归来“遍历父/子关系”的函数称为递归下降。最后,它在遍历过程中处理节点,所以它是一个递归下降处理器。

function ProcessNode(node, outArr) { if (node.nodeType < 3 || node.nodeType > 4) { var atts = node.attributes; if (atts.length > 0) { for (var i = 0; i < atts.length; ++i) { var aNode = atts.item(i); // Attributes are nodes as well! They have a name and value name=value } } if (node.hasChildNodes()) { var newNode = node.firstChild; while (newNode != null) { ProcessNode(newNode, outArr); newNode = newNode.nextSibling; } } } else { // IS A TEXT NODE } }

将HTML可视化的XML推送到GUI

这是使用以下代码片段创建的:

var out = ConcatStringArray(outArr); var gui = new GUIWindow(); gui.SetHTML(out); var doc = gui.GetDocument(); var styleSheet; if (doc.styleSheets.length == 0) { styleSheet = doc.createStyleSheet(); } else { styleSheet = doc.styleSheets[0]; } styleSheet.addRule('body', 'color: black;'); styleSheet.addRule('body', 'font-family: Arial, helvetic, sans-serif;'); styleSheet.addRule('span.nodeName', 'font-weight: 700;'); styleSheet.addRule('ul.attributeList', 'color: #008;'); styleSheet.addRule('li.nodeValue', 'color: #080;'); styleSheet.addRule('*.missing', 'color: #888;'); gui.SetVisible(true);
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485