В главе 3 мы уже кратко описывали основные принципы языка XML, которые необходимы для понимания объектной модели сценариев WS XML. В настоящее время применение XML становится все более широким, поэтому настоящая глава посвящена рассмотрению практических примеров сценариев WSH, которые позволяют анализировать и изменять содержимое файлов в формате XML (естественно, описанные методы анализа и модификации XML-файлов могут применяться и в сценариях, которые встроены в HTML-страницы).
Как известно, основной целью разработки XML являлось создание простого текстового формата для хранения и передачи структурированной информации (иерархичность и объектность описываемых данных — ключевые свойства XML). Основные задачи, решаемые при помощи этой технологии в бизнес-приложениях, таковы:
□ межплатформенный обмен данными между системами разных разработчиков;
□ сбор данных из подразделений организации;
□ обмен коммерческими документами между предприятиями;
□ сбор отчетности государственными органами.
Сейчас библиотеки для работы с XML созданы практически для всех популярных систем разработки приложений и систем управления базами данных. При использовании сценариев WSH также нет необходимости писать собственные программы для разбора XML-формата (такие программы называются парсерами), т.к. встроенный в Windows браузер Internet Explorer версии 4.01 и выше имеет в своем составе в качестве СОМ-объекта парсер MSXML — Microsoft XML library. В настоящей главе для простоты и краткости изложения мы будем пользоваться лишь двумя объектными моделями, которые предоставляет MSXML, не затрагивая рассмотрение таких специфических для XML-файлов понятий, как определения DTD — Documents Type Definitions, используемые для описания и проверки структуры XML-документа, или стилевые таблицы XSL — Extensible Stylesheet Language, предназначенные для формирования на основе данных из XML-источника страницы HTML.
Записная книжка в формате XML
В предыдущей главе мы рассматривали сценарий для работы с записной книжкой, которая хранится в простом текстовом файле book.txt с разделителями. Каждая строка этого файла содержала одну запись в формате Фамилия|Имя|Телефон|Улица|Дом|Кв.|Примечание:
Потапов|Сергей|55-55-55|Моховая|3|10|Без примечаний
Попов|Андрей|56-56-56|Ленина|3|5|Без примечаний
Иванов|Иван|17-17-17|Садовая|4|6|Очень хороший человек
Казаков|Сергей|24-19-68|Полежаева|101|22|Тоже очень хороший человек
Для преобразования файла book.txt к формату XML мы введем теги, описанные в табл. 6.1.
Таблица 6.1. Описание тегов для записной книжки в XML-формате
Тег | Значение |
<PhoneList> | Корневой тег, обозначает начало записной книжки |
<Person> | Обозначает начало новой записи в книжке |
<LastName> | Фамилия человека |
<Name> | Имя |
<Phone> | Телефон |
<Street> | Улица |
<House> | Дом |
<App> | Квартира |
<Note> | Замечания |
Иерархия элементов из таблицы 6.1 показана в листинге 6.1.
Листинг 6.1. Иерархия XML-элементов для записной книжки
Другие записи
Файл book.xml для записной книжки формируется в соответствии с листингом 6.1 (листинг 6.2)
Листинг 6.2. Содержимое файла book.xml
Просмотр XML-файла с помощью объектной модели Internet Explorer 4.0
Если требуется только просматривать и анализировать XML-файл, не модифицируя его, то проще всего воспользоваться объектной моделью MSXML, реализованной в Internet Explorer 4.01.
Замечание
Как отмечено в документации MSDN, эта объектная модель является устаревшей и должна быть заменена моделью XML DOM ( XML Document Object Model ), которая является стандартом корпорации W3C. Однако последняя на момент написания книги версия Internet Explorer 6.0 поддерживает обе эти модели для разбора XML-файлов.
Описание объектной модели
При рассмотрении объектной модели MSXML данные, которые хранятся в XML-файле, удобно представлять в виде иерархического дерева, имеющего один корневой элемент и множество дочерних элементов различного уровня вложенности.
Для анализа содержимого XML-файла используются три объекта: XML Document (объект для работы с XML-документом в целом), XML Element (отвечает за работу с каждым из элементов XML-файла) и Element Collection (коллекция XML-элементов, доступ к которым при помощи метода item() возможен по имени или порядковому номеру).
Полный набор свойств и методов этих трех объектов мы рассматривать не будем; в табл. 6.2 и 6.3 приведено описание нескольких основных свойств объектов XML Document и XML Element, некоторые из них понадобятся нам в дальнейшем при составлении сценария на языке JScript для просмотра записной книжки.
Таблица 6.2. Свойства объекта XML Document
Свойство | Описание |
URL | Задает или возвращает путь к обрабатываемому документу |
root | Содержит корневой элемент XML-документа, Свойство доступно только для чтения |
charset | Возвращает или устанавливает название текущей кодировочной таблицы |
version | Содержит номер версии XML. Свойство доступно только для чтения |
Таблица 6.3. Свойства объекта XML Element
Свойство | Описание |
children | Содержит коллекцию дочерних элементов |
tagName | Содержит имя тега. Свойство доступно для чтения и записи |
text | Возвращает текстовое содержимое элементов и комментариев |
parent | Возвращает указатель на родительский элемент. Ссылки на родительский элемент имеют все элементы, за исключением корневого |
type | Возвращает тип элемента: 0 — элемент, 1 — текст, 2 — комментарий, 3 — Document, 4 — DTD |
Пример сценария
С помощью приведенного ниже сценария SortNameMSXML.js все записи из book.xml сортируются по фамилии и отображаются в Блокноте. Напомним, что аналогичную задачу для текстового файла с разделителями book.txt реализует сценарий SortName.js, приведенный в листинге 5.21. Алгоритм работы сценария SortNameMSXML.js, как и SortName.js, сводится к следующим основным шагам.
1. Информация из файла book.xml считывается в массив PersonArr. Каждый элемент массива является экземпляром объекта Person, в котором хранятся все данные для одного человека.
2. Массив PersonArr сортируется по возрастанию фамилий.
3. Содержимое всех записей из массива PersonArr выводится в текстовый файл out.txt.
4. Файл out.txt открывается в Блокноте.
Таким образом, специфика работы с XML-файлом проявляется лишь при считывании данных из файла book.xml в массив PersonArr. Для этого используется функция FileToArray(). Сначала в этой функции создается пустой массив PersonArr и экземпляр XML объекта XML Document:
PersonArr=new Array();
XML=WScript.CreateObject("MSXML");
В свойство url объекта XML записывается путь к файлу book.xml, который хранится в переменной PathBook:
XML.url=PathBook;
Далее в функции FileToArray о определяется количество элементов
NamRec=XML.root.children.item("Person").length;
В цикле for происходит перебор всех элементов
//Перебираем коллекцию XML-элементов Person
for (i=0; i
//Выделяем в коллекции XML-элементов i-й элемент Person
XItem=XML.root.children.item("Person", i);
//Добавляем новый элемент, в массив объектов Person
PersonToArray(XItem);
}
Как мы видим, каждый элемент
function PersonToArray(XItem) {
//Создаем новый экземпляр PersonRec объекта Person
PersonRec=new Person();
//Заполняем поля объекта PersonRec
PersonRec.LastName=GetTagVal(XItem,"LastName");
PersonRec.Name=GetTagVal(XItem,"Name");
PersonRec.Phone=GetTagVal(XItem,"Phone");
PersonRec.Street=GetTagVal(XItem,"Street");
PersonRec.House=GetTagVal(XItem,"House");
PersonRec.App=GetTagVal(XItem,"App");
PersonRec.Note=GetTagVal(XItem,"Note");
//Сохраняем объект PersonRec в массиве
PersonArr[PersonArr.length]=PersonRec;
}
Поля объекта PersonRec заполняются с помощью функции GetTagVal( obj, tgName ) , которая возвращает значение дочернего для элемента obj элемента с именем tgName :
function GetTagVal(obj, tgName) {
//Возвращаем значение тега tgName
return obj.Children.Item(tgName,0).Text;
}
В листинге 6.3 приводится полный текст сценария SortNameMSXMLjs. Листинг 6.3. Чтение данных из XML-файла с помощью объектной модели Internet Explorer 4.0
/*******************************************************************/
/* Имя: SortNameMSXML.js */
/* Язык: JScript */
/* Описание: Записная книжка (данные в XML-файле book.xml). */
/* Вывод всех записей с сортировкой по фамилии с */
/* помощью объектной модели Internet Explorer 4.0 */
/*******************************************************************/
//Объявляем переменные
var
WshShell,FSO,
BasePath, //Путь к текущему каталогу
PathBook, //Путь к файлу с данными
PathOut, //Путь к выходному файлу
FBook, //Файл с данными
FOut, //Выходной файл
NomRec=0, //Счетчик количества записей
PersonRec, //Объект для хранения данных об одном человеке
PersonArr; //Массив для хранения объектов PersonRec
ForWriting=2; //Константа для создания выходного файла
//Конструктор объекта Person
function Person(LastName,Name,Phone,Street,House,App,Note) {
this.LastName=LastName; //Фамилия
this.Name=Name; //Имя
this.Phone=Phone; //Телефон
this.Street=Street; //Улица
this.House=House; //Дом
this.App=App; //Квартира
this.Note=Note; //Примечание
}
//Определение значения тега tgName XML-элемента obj
function GetTagVal(obj, tgName) {
//Возвращаем значение тега tgName
return obj.Children.Item(tgName,0).Text;
}
//Заполнение нового элемента массива
function PersonToArray(XItem) {
//Создаем новый экземпляр PersonRec объекта Person
PersonRec=new Person();
//Заполняем поля объекта PersonRec
PersonRec.LastName=GetTagVal(XItem,"LastName");
PersonRec.Name=GetTagVal(XItem,"Name");
PersonRec.Phone=GetTagVal(XItem,"Phone");
PersonRec.Street=GetTagVal(XItem,"Street");
PersonRec.House=GetTagVal(XItem,"House");
PersonRec.App=GetTagVal(XItem,"App");
PersonRec.Note=GetTagVal(XItem,"Note");
//Сохраняем объект PersonRec в массиве
PersonArr[PersonArr.length]=PersonRec;
}
//Создание массива объектов Person
function FileToArray() {
var
XML,NomRec,XItem,ex;
//Создаем массив PersonArr
PersonArr=new Array();
//Создаем объект MSXML
XML=WScript.CreateObject("MSXML");
//Задаем путь к файлу с данными
XML.url=PathBook;
//Инициализируем счетчик числа элементов Person
//в XML-файле
NomRec=0;
try {
//Определяем число элементов Person в XML-файле
NomRec=XML.root.children.item("Person").length;
if (typeof(NomRec)=="undefined") NomRec=1;
} catch (ex) {
NomRec=0;
}
//Перебираем коллекцию XML-элементов Person
for (i=0;i
//Выделяем в коллекции XML-элементов i-й элемент Person
XItem=XML.root.children.item("Person",i);
//Добавляем новый элемент в массив объектов Person
PersonToArray(XItem);
}
}
//Запись в выходной файл заголовка отчета
function TopReport(Mess) {
FOut.WriteLine(Mess);
FOut.WriteLine("--------------------");
FOut.WriteLine("");
}
//Запись в выходной файл итоговой информации
function BottomReport() {
FOut.WriteLine("Всего записей: "+NomRec);
}
//Запись данных из объекта Person в выходной файл
function PrintPerson(PersRec) {
FOut.WriteLine("Фамилия: "+PersRec.LastName);
FOut.WriteLine("Имя: "+PersRec.Name);
FOut.WriteLine("Телефон: "+PersRec.Phone);
FOut.WriteLine("Улица: "+PersRec.Street);
FOut.WriteLine("Дом: "+PersRec.House);
FOut.WriteLine("Кв.: "+PersRec.App);
FOut.WriteLine("Заметки: "+PersRec.Note);
FOut.WriteLine("*********************************");
NomRec++;
}
//Сортировка массива и вывод его содержимого в выходной файл
function ListPersonArray() {
var i,a;
//Сортировка массива по фамилии
PersonArr.sort(SortLastName);
//Цикл по всем элементам массива PersonArr
for (i=0;i<=PersonArr.length-1;i++) {
//Запись информации в выходной файл
PrintPerson(PersonArr[i]);
}
}
//Функция для сортировки массива по фамилии
function SortLastName(Pers1,Pers2) {
if (Pers1.LastName
else if (Pers1.LastName==Pers2.LastName) return 0;
else return 1;
}
//Вывод содержимого файла с данными
function ListFile() {
//Считывание данных из файла в массив
FileToArray();
//Запись информации из массива в выходной файл
ListPersonArray();
}
//Просмотр содержимого выходного файла в Блокноте
function MakeOut() {
//Закрываем выходной файл
FOut.Close();
//Открываем выходной файл в Блокноте
WshShell.Run("notepad "+PathOut,1);
}
//Построение путей к файлам
function InitPath() {
BasePath=WshShell.CurrentDirectory+"\\";
//Путь к файлу с данными
PathBook=BasePath+"book.xml",
//Путь к выходному файлу
PathOut=BasePath+"out.txt";
}
//Основная запускная функция
function Main() {
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
//Создаем объект FileSystemObject
FSO=WScript.CreateObject("Scripting.FileSystemObject");
//Открываем выходной файл для записи
FOut=FSO.OpenTextFile(PathOut,ForWriting,true);
//Печатаем заголовок отчета
TopReport("Сортировка по фамилии");
//Выводим содержимого файла с данными
ListFile();
//Печатаем итоговую информацию
BottomReport("Всего записей: "+PersonArr.length);
//Открываем выходной файл в Блокноте
MakeOut();
}
/******************* Начало **********************************/
Main();
/************* Конец *********************************************/
Использование XML DOM для просмотра и изменения ХМL-файла
Объектная модель XML DOM (XML Document Object Model, объектная модель документа XML) является рекомендованным корпорацией W3C стандартом, который определяет интерфейсы, с помощью которых приложения могут загружать XML-файл, просматривать его содержимое, производить поиск, добавление, изменение и удаление данных, сохранять сделанные изменения в файле. Отметим, что в модели XML DOM документ в формате XML рассматривается как иерархическое дерево, которое состоит из элементов, называемых узлами (nodes), и имеет один корневой элемент (узел).
Замечание
В дальнейшем в этой главе терминами "элемент" и "узел" мы будем пользоваться как синонимами.
Описание модели XML DOM
Парсер MSXML поддерживает много объектов, определяемых в модели XML DOM, с помощью которых можно решать связанные с XML задачи различного уровня сложности. Нам в дальнейшем для написания сценариев, которые осуществляют просмотр записной книжки в XML-формате, а также поиск, добавление и удаление записей из этой книжки, понадобятся только три основных объекта: DOMDocument (представляет XML-документ в целом), XMLDOMNode (представляет одиночный XML-элемент, т. е. один узел в дереве) и XMLDOMNodeList (коллекция элементов, являющихся дочерними по отношению к определенному узлу в дереве, доступ к которым возможен по порядковому номеру при помощи метода item()).
В свою очередь, объекты DOMDocument и XMLDOMNode имеют множество свойств и методов, некоторые из них (включая все свойства и методы, которые используются при написании сценариев для работы с записной книжкой) описаны в табл. 6.4–6.6.
Таблица 6.4. Свойства и методы объекта DOMDocument
Название | Тип | Описание |
childNodes | Свойство | Содержит коллекцию всех узлов документа. Свойство доступно только для чтения |
documentElement | Свойство | Содержит ссылку на корневой элемент документа. Свойство доступно как для чтения, так и для записи |
getElementsByTagName( tagName ) | Метод | Возвращает коллекцию всех элементов в документе, имеющих имя, которое задается параметром tagName |
hasChildNodes() | Метод | Возвращает true , если в документе есть элементы. В противном случае возвращает false |
load(url) | Метод | Загружает XML-документ из файла, путь к которому задан параметром url |
loadXML( xmlString ) | Метод | Загружает XML-документ, содержимое которого содержится в строке xmlString |
url | Свойство | Содержит путь к загруженному XML-документу. Для того чтобы изменить это свойство, нужно заново загрузить документ с помощью метода load |
Таблица 6.5. Свойства объекта XMLDOMNode
Название | Описание |
attributes | Содержит список атрибутов узла. Свойство доступно только для чтения |
childNodes | Содержит коллекцию всех узлов, которые являются дочерними по отношению к данному узлу. Свойство доступно только для чтения |
firstChild | Содержит ссылку на первый дочерний узел. Свойство доступно только для чтения |
lastChild | Содержит ссылку на последний дочерний узел. Свойство доступно только для чтения |
nodeName | Содержит имя узла. Свойство доступно только для чтения |
parentNode | Содержит ссылку на родительский узел (для тех узлов, которые имеют родительский элемент). Свойство доступно только для чтения |
text | Возвращает или устанавливает текстовое содержимое узла |
Таблица 6.6. Методы объекта XMLDOMNode
Название | Описание |
appendChild( NewElem ) | Добавляет новый элемент NewElem в качестве последнего дочернего элемента. В качестве результата возвращает ссылку на добавленный узел |
cloneNode( deep ) | Создает новый узел, который является точной копией текущего узла. Параметр deep — это логическая константа, которая указывает, нужно ли при создании нового узла копировать дочерние узлы текущего элемента ( deep =true) , либо этого делать не следует ( deep =true) |
hasChildNodes() | Возвращает true , если у узла есть дочерние элементы. В противном случае возвращает false |
removeChild( OldElem ) | Удаляет дочерний элемент, ссылка на который содержится в параметре OldElem |
replaceChild( OldElem, NewElem ) | Заменяет элемент, ссылка на который содержится в параметре OldElem , на элемент, ссылка на который содержится в параметре NewElem |
selectNodes( patternString ) | Производит поиск дочерних элементов, содержимое которых удовлетворяет шаблону поиска patternString . В результате возвращает объект XMLDOMNodeList , содержащий коллекцию всех найденных узлов |
selectSingleNode( patternString ) | Производит поиск первого дочернего элемента, содержимое которого удовлетворяет шаблону поиска patternString . В случае удачного поиска возвращает ссылку на найденный элемент, в противном случае возвращает Null |
Просмотр содержимого записной книжки
Для того чтобы использовать схему XML DOM в сценарии SortNameMSXML.js, осуществляющем вывод информации из XML-файла book.xml в Блокнот, нужно внести изменения в три функции: GetTagVal( obj, tgName ) , PersonToArray( XNode ) и FileToArray(). Сценарий, который получится в результате этих изменений, назовем SortNameXMLDOM.js.
В функции FileToArray() сначала создается пустой массив PersonArr и экземпляр XML объекта DOMDocument:
PersonArr=new Array();
XML = WScript.CreateObject("Msxml.DOMDocument");
Для загрузки содержимого файла book.xml (путь к этому файлу хранится в переменной PathBook) в объект xml, используется метод load:
XML.load(PathBook);
Указатель на корневой элемент записывается в переменную Root с помощью свойства documentElement объекта XML:
Root=XML.documentElement;
После этого нам остается в цикле перебрать все элементы Person (для корневого элемента они являются дочерними элементами первого уровня вложенности) и для каждого из них вызвать функцию PersonToArray():
for (i=1; i<=Root.childNodes.length-1; i++) {
//Выделяем в коллекции XML-элементов i-й элемент
//первого уровня вложенности
CurrNode=Root.childNodes.item(i);
//Добавляем новый элемент в массив объектов Person
PersonToArray(CurrNode);
}
Функция PersonToArray( XNode ) в SortNameXMLDOM.js имеет тот же вид, что и в сценарии SortNameMSXML.js:
function PersonToArray(XNode) {
//Создаем новый экземпляр PersonRec объекта Person
PersonRec=new Person();
//Заполняем поля объекта PersonRec
PersonRec.LastName=GetTagVal(XNode,"LastName");
PersonRec.Name=GetTagVal(XNode,"Name");
PersonRec.Phone=GetTagVal(XNode,"Phone");
PersonRec.Street=GetTagVal(XNode,"Street");
PersonRec.House=GetTagVal(XNode,"House");
PersonRec.App=GetTagVal(XNode,"App");
PersonRec.Note=GetTagVal(XNode,"Note");
//Сохраняем объект PersonRec в массиве
PersonArr[PersonArr.length]=PersonRec;
}
Здесь для построения функции GetTagVal( obj, tgName ) , которая возвращает значение дочернего для элемента obj элемента с именем tgName , используется метод getElementsByTagName, возвращающий коллекцию дочерних элементов с заданным именем:
function GetTagVal(obj, tgName) {
var ElemList;
//Создаем коллекцию дочерних для obj элементов, которые
//задаются тегом tgName
ElemList=obj.getElementsByTagName(tgName);
//Проверяем, есть ли в коллекции ElemList элементы
if (ElemList.length>0)
//Возвращаем значение первого встретившегося элемента tgName
return ElemList.item(0).text
else return "";
}
В листинге 6.4 приводится полный текст сценария SortNameXMLDOM.js.
Листинг 6.4. Чтение данных из XML-файла с помощью XML DOM
/*******************************************************************/
/* Имя: SortNameXMLDOM.js */
/* Язык: JScript */
/* Описание: Записная книжка (данные в XML-файле book.xml). */
/* Вывод всех записей с сортировкой по фамилии с */
/* помощью объектной модели XML DOM */
/*******************************************************************/
//Объявляем переменные
var
WshShell,FSO,
BasePath, //Путь к текущему каталогу
PathBook, //Путь к файлу с данными
PathOut, //Путь к выходному файлу
FBook, //Файл с данными
FOut, //Выходной файл
NomRec=0, //Счетчик количества записей
PersonRec, //Объект для хранения данных об одном человеке
PersonArr; //Массив для хранения объектов PersonRec
ForWriting=2; //Константа для создания выходного файла
//Конструктор объекта Person
function Person(LastName,Name,Phone,Street,House,App,Note) {
this.LastName=LastName; //Фамилия
this.Name=Name; //Имя
this.Phone=Phone; //Телефон
this.Street=Street; //Улица
this.House=House; //Дом
this.App=App; //Квартира
this.Note=Note; //Примечание
}
//Определение значения тега tgName XML-элемента obj
function GetTagVal(obj, tgName) {
var ElemList;
//Создаем коллекцию дочерних для obj элементов, которые
//задаются тегом tgName
ElemList=obj.getElementsByTagName(tgName);
//Проверяем, есть ли в коллекции ElemList элементы
if (ElemList.length>0)
//Возвращаем значение первого встретившегося элемента tgName
return ElemList.item(0).text
else return "";
}
//Заполнение нового элемента массива
function PersonToArray(XNode) {
//Создаем новый экземпляр PersonRec объекта Person
PersonRec=new Person();
//Заполняем поля объекта PersonRec
PersonRec.LastName=GetTagVal(XNode,"LastName");
PersonRec.Name=GetTagVal(XNode,"Name");
PersonRec.Phone=GetTagVal(XNode,"Phone");
PersonRec.Street=GetTagVal(XNode,"Street");
PersonRec.House=GetTagVal(XNode,"House");
PersonRec.App=GetTagVal(XNode,"App");
PersonRec.Note=GetTagVal(XNode,"Note");
//Сохраняем объект PersonRec в массиве
PersonArr[PersonArr.length]=PersonRec;
}
//Создание массива объектов Person
function FileToArray() {
var XML,Root,NomRec,CurrNode,ex,i;
//Создаем массив PersonArr
PersonArr=new Array();
//Создаем объект XML DOM
XML = WScript.CreateObject("Msxml.DOMDocument");
//Загружаем XML-документ из файла
XML.load(PathBook);
//Сохраняем в переменной Root ссылку на корневой элемент документа
Root=XML.documentElement;
//Перебираем все дочерние элементы первого уровня вложенности
//для корневого элемента
for (i=1; i<=Root.childNodes.length-1;i++) {
//Выделяем в коллекции XML-элементов i-й элемент
CurrNode=Root.childNodes.item(i);
//Добавляем новый элемент в массив объектов Person
PersonToArray(CurrNode);
}
}
//Запись в выходной файл заголовка отчета
function TopReport(Mess) {
FOut.WriteLine(Mess);
FOut.WriteLine("--------------------");
FOut.WriteLine("");
}
//Запись в выходной файл итоговой информации
function BottomReport(Mess) {
FOut.WriteLine(Mess);
}
//Запись данных из объекта Person в выходной файл
function PrintPerson(PersRec) {
FOut.WriteLine("Фамилия: "+PersRec.LastName);
FOut.WriteLine("Имя: "+PersRec.Name);
FOut.WriteLine("Телефон: "+PersRec.Phone);
FOut.WriteLine("Улица: "+PersRec.Street);
FOut.WriteLine("Дом: "+PersRec.House);
FOut.WriteLine("Кв.: "+PersRec.App);
FOut.WriteLine("Заметки: "+PersRec.Note);
FOut.WriteLine("*********************************");
NomRec++;
}
//Сортировка массива и вывод его содержимого в выходной файл
function ListPersonArray() {
var i;
//Сортировка массива по фамилии
PersonArr.sort(SortLastName);
//Цикл по всем элементам массива PersonArr
for (i=0;i<=PersonArr.length-1;i++) {
//Запись информации в выходной файл
PrintPerson(PersonArr[i]);
}
}
//Функция для сортировки массива по фамилии
function SortLastName(Pers1,Pers2) {
if (Pers1.LastName
else if (Pers1.LastName==Pers2.LastName) return 0;
else return 1;
}
//Вывод содержимого файла с данными
function ListFile() {
//Считывание данных из файла в массив
FileToArray();
//Запись информации из массива в выходной файл
ListPersonArray();
}
//Просмотр содержимого выходного файла в Блокноте
function MakeOut() {
//Закрываем выходной файл
FOut.Close();
//Открываем выходной файл в Блокноте
WshShell.Run("notepad "+PathOut,1);
}
//Построение путей к файлам
function InitPath() {
BasePath=WshShell.CurrentDirectory+"\\";
//Путь к файлу с данными
PathBook=BasePath+"book.xml",
//Путь к выходному файлу
PathOut=BasePath+"out.txt";
}
//Основная запускная функция
function Main() {
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
//Создаем объект FileSystemObject
FSO=WScript.CreateObject("Scripting.FileSystemObject");
//Открываем выходной файл для записи
FOut=FSO.OpenTextFile(PathOut,ForWriting,true);
//Печатаем заголовок отчета
TopReport("Сортировка по фамилии");
//Выводим содержимого файла с данными
ListFile();
//Печатаем итоговую информацию
BottomReport("Всего записей: "+PersonArr.length);
//Открываем выходной файл в Блокноте
MakeOut();
}
/******************* Начало **********************************/
Main();
/************* Конец *********************************************/
Добавление информации в записную книжку
В принципе можно добавлять информацию в записную книжку, просто записывая строки с соответствующими тегами в текстовый файл book.xml. Однако лучше для этой цели воспользоваться специальными методами XML DOM (в этом случае не нужно, например, заботиться о закрывающих тегах).
Для иллюстрации методов XML DOM, позволяющих записывать данные в XML-файл, рассмотрим сценарий AddRecord.js, в котором производится добавление в book.xml следующей записи:
Процесс добавления записи в книжку осуществляется в функции AddRecord(). Здесь сначала заполняются нужными значениями поля объекта PersonRec (функция MakePersonRec()), а затем данные из PersonRec добавляются в файл book.xml (функция RecordToFile(PersonRec)):
function AddRecord() {
//Заполняем поля объекта PersonRec
MakePersonRec();
//Сохраняем данные из объекта PersonRec в XML-файле
RecordToFile(PersonRec);
}
Итак, наиболее важной в сценарии является функция RecordToFile( PersonRec ) . В этой функции сначала создается экземпляр XMLDoc объекта DOMDocument и с помощью метода load загружается файл book.xml:
XMLDoc = WScript.CreateObject("Msxml.DOMDocument");
XMLDoc.load(PathBook);
Указатель на корневой элемент сохраняется в переменной Root:
Root=XMLDoc.documentElement;
После этого с помощью метода createElement создается новый элемент Person, который затем добавляется в book.xml (метод appendChild):
//Создаем XML-элемент Person
NewElem=XMLDoc.createElement("Person");
//Добавляем новый элемент в XML-файл
Root.appendChild(NewElem);
Другие добавляемые элементы (LastName, Name, Phone, Street, House, App и Note) должны быть дочерними относительно элемента Person, поэтому в переменной Root мы сохраним ссылку на последний добавленный элемент Person:
Root=Root.lastChild;
Все элементы добавляются с помощью вызовов методов createElement и appendChild, например:
//Создаем элемент LastName
NewElem=XMLDoc.createElement("LastName");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
Содержимое добавляемых элементов (свойство text) берется из соответствующих полей объекта PersRec, например:
//Подставляем в качестве содержимого элемента LastName
//значение поля LastName объекта PersRec
Root.lastChild.text=PersRec.LastName;
После того как все нужные элементы добавлены, измененный файл book.xml с помощью метода save сохраняется на жестком диске:
XMLDoc.save(PathBook);
Полный текст сценария AddRecord.js приводится в листинге 6.5.
Листинг 6.5. Добавление данных в XML-файл с помощью XML DOM
/*******************************************************************/
/* Имя: AddRecord.js */
/* Язык: JScript */
/* Описание: Записная книжка (данные в XML-файле book.xml). */
/* Вставка новых элементов в XML-файл */
/*******************************************************************/
//Объявляем переменные
var
WshShell,
BasePath, //Путь к текущему каталогу
PathBook, //Путь к файлу с данными
XMLDoc, //XML-файл с данными
NomRec=0, //Счетчик количества записей
PersonRec, //Объект для хранения данных об одном человеке
PersonArr; //Массив для хранения объектов PersonRec
//Инициализируем константы для диалоговых окон
var vbYesNo=4,vbQuestion=32,vbInformation=64,vbYes=6,vbOkOnly=0;
//Конструктор объекта Person
function Person(LastName,Name,Phone,Street,House,App,Note) {
this.LastName=LastName; //Фамилия
this.Name=Name; //Имя
this.Phone=Phone; //Телефон
this.Street=Street; //Улица
this.House=House; //Дом
this.App=App; //Квартира
this.Note=Note; //Примечание
}
//Заполнение полей объекта PersonRec
function MakePersonRec() {
//Создаем экземпляр PersonRec объекта Person
PersonRec=new Person();
//Заполняем поля объекта PersonRec
PersonRec.LastName="Сидоров";
PersonRec.Name="Антон";
PersonRec.Phone="18-18-18";
PersonRec.Street="Саранская";
PersonRec.House="12";
PersonRec.App="4";
PersonRec.Note="Запись добавлена из сценария";
}
//Сохранение данных из объекта PersonRec в XML-файле
function RecordToFile(PersRec) {
//Объявляем переменные
var Root,NewElem,s;
//Создаем объект DOMDocument
XMLDoc = WScript.CreateObject("Msxml.DOMDocument");
//Загружаем XML-файл
XMLDoc.load(PathBook);
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XMLDoc.documentElement;
//Создаем XML-элемент Person
NewElem=XMLDoc.createElement("Person");
//Добавляем новый элемент в XML-файл
Root.appendChild(NewElem);
//Сохраняем в переменной Root ссылку на последний добавленный
//элемент Person
Root=Root.lastChild;
//Создаем элемент LastName
NewElem=XMLDoc.createElement("LastName");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента LastName
//значение поля LastName объекта PersRec
Root.lastChild.text=PersRec.LastName;
//Создаем элемент Name
NewElem=XMLDoc.createElement("Name");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента Name
//значение поля Name объекта PersRec
Root.lastChild.text=PersRec.Name;
//Создаем элемент Phone
NewElem=XMLDoc.createElement("Phone");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента Phone
//значение поля Phone объекта PersRec
Root.lastChild.text=PersRec.Phone;
//Создаем элемент Street
NewElem=XMLDoc.createElement("Street");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента Street
//значение поля Street объекта PersRec
Root.lastChild.text=PersRec.Street;
//Создаем элемент House
NewElem=XMLDoc.createElement("House");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента House
//значение поля House объекта PersRec
Root.lastChild.text=PersRec.House;
//Создаем элемент App
NewElem=XMLDoc.createElement("App");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента App
//значение поля House объекта PersRec
Root.lastChild.text=PersRec.App;
//Создаем элемент Note
NewElem=XMLDoc.createElement("Note");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента App
//значение поля House объекта PersRec
Root.lastChild.text=PersRec.Note;
//Сохраняем содержимое XML-файла на диске
XMLDoc.save(PathBook);
}
//Добавление новой записи в книжку
function AddRecord() {
//Заполняем поля объекта PersonRec
MakePersonRec();
//Сохраняем данные из объекта PersonRec в XML-файл
RecordToFile(PersonRec);
}
//Построение путей к файлам
function InitPath() {
BasePath=WshShell.CurrentDirectory+"\\";
//Путь к файлу с данными
PathBook=BasePath+"book.xml";
}
//Основная запускная функция
function Main() {
var Res;
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
//Запрос на создание нового ключа
Res=WshShell.Popup("Добавить запись в \n"+PathBook+"?", 0,
"Работа с XML-файлом", vbQuestion+vbYesNo);
if (Res==vbYes) { //Нажата кнопка Да
//Добавляем новую запись в книжку
AddRecord();
//Выводим информацию на экран
WshShell.Popup("Новая запись\n\n"+PersonRec.LastName+" "+
PersonRec.Name+"\n"+PersonRec.Phone+"\n"+
PersonRec.Street+", "+PersonRec.House+"-"+PersonRec.App+"\n\n"+
"добавлена в файл "+PathBook, 0,
"Работа с XML-файлом", vbInformation+vbOkOnly);
}
}
/******************* Начало **********************************/
Main();
/************* Конец *********************************************/
Поиск и удаление записи из книжки
Рассмотрим сценарий FindAndDelRecord.wsf, с помощью которого можно будет полностью удалить из записной книжки данные о человеке, фамилия которого введена в диалоговом окне (рис. 6.1).
Рис. 6.1. Ввод фамилии для удаления
Сценарий FindAndDelRecord.wsf реализован в виде WS-файла для того, чтобы можно было внутри JScript-кода воспользоваться функцией InputName на языке VBScript, которая реализует диалоговое окно с полем ввода, показанное на рис. 6.1:
Function InputName
'Вводим фамилию в диалоговом окне
InputName = InputBox("Введите фамилию для удаления:", "Записная книжка")
End Function
Фамилия, которую следует найти и удалить в записной книжке, сохраняется в глобальной переменной LastName:
LastName=InputName();
Непосредственно поиск и удаление данных производятся в функции FindAndDelRecord(). Здесь, как и во всех рассмотренных ранее примерах, сначала создается экземпляр XMLDoc объекта DOMDocument, с помощью метода load загружается файл book.xml и указатель на корневой элемент сохраняется в переменной Root:
XMLDoc = WScript.CreateObject("Msxml.DOMDocument");
XMLDoc.load(PathBook);
Root=XMLDoc.documentElement;
Для выделения в записной книжке всех фамилий, которые требуется удалить, используется метод selectNodes(). В качестве аргумента этого метода подставляется строка sSelect, которая указывает, что нужно искать расположенные внутри элементов Person элементы с именем LastName и значением, которое совпадает со значением переменной LastName. Все найденные элементы помещаются в коллекцию NodeList:
//Формируем строку для поиска фамилии
sSelect="Person/LastName[text()='"+LastName+"']";
//Создаем коллекцию NodeList всех элементов LastName,
//значение которых совпадает со значением переменной LastName
NodeList=XMLDoc.documentElement.selectNodes(sSelect);
Если найден хотя бы один подходящий элемент LastName, т.е. коллекция NodeList не является пустой, то для каждого такого элемента в цикле for определяется родительский элемент (в нашем случае это элемент Person) и этот элемент вместе со всеми своими дочерними элементами удаляется с помощью метода removeChild():
for (i=0;i<=NodeList.length-1;i++) {
//Определяем родительский элемент (Person) для найденного
//элемента LastName
Parent=NodeList.item(i).parentNode;
//Удаляем элемент Person вместе со всеми его дочерними элементами
Root.removeChild(Parent);
//Выводим диалоговое окно с сообщением
WshShell.Popup("Запись удалена!",0,
"Работа с XML-файлом",vbInformation+vbOkOnly);
}
После удаления всех записей содержимое XML-файла book.xml сохраняется на диске с помощью метода save():
XMLDoc.save(PathBook);
Полный текст сценария FindAndDelRecord.wsf приводится в листинге 6.6.
Листинг 6.6. Поиск и удаление данных в XML-файле с помощью XML DOM
Имя: FindAndDelRecord.wsf
Описание: Записная книжка (данные в XML-файле book.xml).
Поиск и удаление элементов из XML-файла