Перейти на главную страничку сайта (список статей, файлы для скачивания)

ФОРУМ (здесь можно обсудить эту статью, а также любые проблемы программирования на различных макроязыках и в скриптовых средах)

Сценарии объектной модели документа DOM XML средствами OLE-Automation

MS XML Parser как OLE-сервер

Библиотека MS XML Parser предоставляет возможность работы с XML-документами в скриптах, использующих объектную модель DOM XML. Такая работа возможна практически в любых средах, способных выступить в роли OLE-клиента. В данной статье примеры скриптов будут приводиться на языке VBScript для административных скриптов Windows. Вы можете копировать содержимое подобных примеров в текстовые файлы с расширением .vbs и запускать эти файлы на исполнение двойным щелчком мыши или из командной строки с помощью интерпретатора cscript.exe.

Объект DOMDocument создаётся следующим образом:

Set xmlParser = CreateObject("Msxml2.DOMDocument")

После этого вы можете вызывать и использовать методы и свойства этого объекта для чтения и записи XML-документов. Примечание: методы объектов XMLDOMDocument и XMLDOMElement во многом сходны, поэтому рассматриваются в данной статье совместно. Описание свойств, методов и событий в данной статье не является полностью исчерпывающим. Полное описание объектной модели MS XML Parser вы можете получить в MSDN, воспользовавшись, например, поиском по словосочетанию "IXMLDOMDocument/DOMDocument Members" или "IXMLDOMElement Members".

Пример XML-документа

В примерах кода, приведённых ниже, используется следующий "образцовый" XML-документ, представляющий из себя некий абстрактный упрощённый каталог товаров:

<?xml version="1.0"?>
<!DOCTYPE PRODUCTS
     [
     <!ELEMENT PRODUCTS (PRODUCT)*>
     <!ELEMENT PRODUCT (TITLE, SORT+)>
     <!ELEMENT TITLE (#PCDATA)>
     <!ELEMENT COLOR (#PCDATA)>
     <!ELEMENT PRICE (#PCDATA)>
     <!ELEMENT SORT (COLOR, PRICE)>
     <!ATTLIST PRODUCT import (yes | no) "no">
     ]
>
<PRODUCTS>
    <PRODUCT import="yes">
        <TITLE> Product #1 </TITLE>
        <SORT>
            <COLOR> red </COLOR>
            <PRICE> $10.00 </PRICE>
        </SORT>
        <SORT>
            <COLOR> blue </COLOR>
            <PRICE> $11.00 </PRICE>
        </SORT>
        <SORT>
            <COLOR> gray </COLOR>
            <PRICE> $16.00 </PRICE>
        </SORT>
    </PRODUCT>
    <PRODUCT>
        <TITLE> Product #2 </TITLE>
        <SORT>
            <COLOR> red </COLOR>
            <PRICE> $20.00 </PRICE>
        </SORT>
        <SORT>
            <COLOR> green </COLOR>
            <PRICE> $22.00 </PRICE>
        </SORT>
    </PRODUCT>
    <PRODUCT import="yes">
        <TITLE> Product #3 </TITLE>
        <SORT>
            <COLOR> red </COLOR>
            <PRICE> $30.00 </PRICE>
        </SORT>
        <SORT>
            <COLOR> blue </COLOR>
            <PRICE> $33.00 </PRICE>
        </SORT>
    </PRODUCT>
    <PRODUCT>
        <TITLE> Product #4 </TITLE>
        <SORT>
            <COLOR> red </COLOR>
            <PRICE> $40.00 </PRICE>
        </SORT>
        <SORT>
            <COLOR> blue </COLOR>
            <PRICE> $44.00 </PRICE>
        </SORT>
    </PRODUCT>
    <PRODUCT>
        <TITLE> Product #5 </TITLE>
        <SORT>
            <COLOR> red </COLOR>
            <PRICE> $50.00 </PRICE>
        </SORT>
        <SORT>
            <COLOR> gray </COLOR>
            <PRICE> $55.00 </PRICE>
        </SORT>
    </PRODUCT>
</PRODUCTS>

Вот XSL-таблица стилей для вышеприведённого документа, которая также является обычным XML-документом:

<?xml version="1.0" encoding="windows-1251"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
	<H1>Каталог товаров</H1>
	<xsl:apply-templates select="PRODUCTS/PRODUCT" />
</xsl:template>
<xsl:template match="PRODUCT">
	<SPAN style="font-style:italic">Наименование:</SPAN>
	<xsl:value-of select="TITLE" /> <BR />
	<SPAN style="font-style:italic">Импортный:</SPAN>
	<xsl:value-of select="@import" /> <BR />
	<TABLE border="1" width="100%" cellspacing="0">
	<xsl:apply-templates select="SORT" />
	</TABLE>
	<BR />
</xsl:template>
<xsl:template match="SORT">
	<TR>
	<TD><xsl:value-of select="COLOR" /></TD>
	<TD><xsl:value-of select="PRICE" /></TD>
	</TR>
</xsl:template>
</xsl:stylesheet>

Загрузка XML-документа, отслеживание ошибок

Перечень свойств, методов и событий:

Описание
async Булево. Чтение и запись. Истина, если разрешена асинхронная загрузка документа. По умолчанию - истина. Если свойство установлено в True, метод load вернёт управление раньше, чем загрузка будет завершена. В этом случае вы можете использовать свойство readyState для проверки состояния загрузки, обрабатывая событие onreadystatechange.
parsed Булево. Только для чтения. Определяет состояние разборки узла и его дочерних узлов. В процессе асинхронного доступа в какой-то конкретный момент может оказаться доступным не все дерево документа. Перед выполнением некоторых операций, типа преобразований XSLT, полезно знать, доступно ли все дерево ниже этого узла для обработки.
parseError Только для чтения. Возвращает ссылку на объект XMLDOMParseError, при помощи которого можно получить подробную информацию о последней ошибке анализатора.
readyState Только для чтения. Возвращает целое число, характеризующее текущее состояние анализатора:
  • LOADING (1) - находится в процессе загрузки документа.
  • LOADED (2) - загрузка завершена, но объектная модель документа ещё не доступна.
  • INTERACTIVE (3) - объектная модель создана (все элементы разобраны, установлены их связи и атрибуты), но доступна пока только для чтения.
  • COMPLETED (4) - документ разобран, с ошибками или без.
resolveExternals Булево. Чтение и запись. По умолчанию - истина. Определяет, должны ли быть разрешены во время разбора внешние определения - пространства имён, внешние подмножества DTD и ссылки на внешние примитивы, независимо от проверки на валидность. Если задано True, внешние определения разрешаются во время разбора. Это позволяет определить атрибуты по умолчанию и типы данных и использовать внешнее подмножество DTD. Эта установка независима от того, должна ли быть выполнена проверка на валидность (что задаётся значением свойства validateOnParse). Если внешнее определение не может быть разрешено в процессе разбора, происходит ошибка.
validateOnParse Булево. Чтение и запись. По умолчанию - истина. Определяет, должен ли парсер проверить документ на валидность. Если установлено False, осуществляется только проверка на корректно сформированный (well-formed) документ.
abort() Прерывание процесса асинхронной загрузки и обработки документа. Объект XMLDOMParseError будет содержать информацию об ошибке. Если загрузка уже завершена (свойство readyState равно 4), никакие действия не предпринимаются.
load(xmlSource) Загружает документ, URL которого задан параметром xmlSource. В случае успеха возвращает True. Вызов этого метода обнуляет содержимое текущего документа. Если указанный URL не доступен или не ссылается на документ XML, этот метод возвращает ошибку и устанавливает свойство documentElement в null. Вы можете использовать этот метод, чтобы проверить, правильно ли построен (well-formed) документ XML. Вы не можете использовать этот метод, чтобы проверить документ на валидность.
loadXML(strXML) Загружает XML-фрагмент из передаваемой строки. Вы можете использовать этот метод, чтобы проверить, правильно ли построен (well-formed) документ XML. Вы не можете использовать этот метод, чтобы проверить документ на валидность.
ondataavailable Событие вызывается, когда обработчик обрабатывает очередную порцию данных документа. В обработчике этого события можно проверять текущий статус асинхронной загрузки (значение свойства readyState).
onreadystatechange Событие вызывается каждый раз, когда изменяется состояние обработчика - значение свойства readyState.

Свойства объекта XMLDOMParseError (все свойства доступны только для чтения):

Описание
errorCode Содержит код возникшей ошибки или нуль, если ошибки не случилось.
filepos Содержит смещение относительно начала файла, в котором обнаружена ошибка.
line Содержит номер строки, в которой обнаружена ошибка.
linepos Содержит позицию ошибки в строке, в которой обнаружена ошибка.
reason Содержит описание ошибки.
srcText Содержит полный текст строки, в которой обнаружена ошибка.
url Содержит URL обрабатываемого документа.

Пример скрипта, осуществляющего загрузку XML-документа с проверкой на ошибки:

'Создаём OLE-объект DOMDocument
Set xmlParser = CreateObject("Msxml2.DOMDocument")
'Отключаем асинхронную загрузку
xmlParser.async = False
'Загружаем XML-документ
xmlParser.load "C:\Sample.xml"
'Если случилась ошибка, выдаём информацию о ней и завершаем работу
If xmlParser.parseError.errorCode Then
	ShowError xmlParser.parseError
	WScript.Quit
End If
'Выводим содержимое XML-документа
WScript.Echo xmlParser.xml
'Освобождаем объектную переменную
Set xmlParser = Nothing
'******************************************************************************
Function ShowError(XMLDOMParseError)
	mess = _
	"parseError.errorCode: " & XMLDOMParseError.errorCode & vbCrLf & _
	"parseError.filepos: " & XMLDOMParseError.filepos & vbCrLf & _
	"parseError.line: " & XMLDOMParseError.line & vbCrLf & _
	"parseError.linepos: " & XMLDOMParseError.linepos & vbCrLf & _
	"parseError.reason: " & XMLDOMParseError.reason & vbCrLf & _
	"parseError.srcText: " & XMLDOMParseError.srcText & vbCrLf & _
	"parseError.url: " & XMLDOMParseError.url & vbCrLf
	WScript.Echo mess
End Function

Пример асинхронной загрузки XML-документа:

Set xmlParser = WScript.CreateObject("Msxml2.DOMDocument","xmlParser_")
xmlParser.load "C:\Sample.xml"
'******************************************************************************
Function xmlParser_onreadystatechange()
	WScript.Echo "readyState = " & xmlParser.readyState
	If xmlParser.readyState = 4 Then
		WScript.Echo xmlParser.xml
	End If
End Function

Обход дерева элементов

Перечень свойств и методов:

Описание
documentElement Содержит узел, представляющий корневой элемент документа (объект XMLDOMElement). Чтение и запись. Возможно присвоение ссылки на другой объект созданного ранее документа.
childNodes Содержит коллекцию (объект XMLDOMNodeList) всех дочерних узлов-неатрибутов данного узла. Только чтение.
firstChild Содержит первый дочерний узел данного узла, не являющийся атрибутом. Только чтение.
lastChild Содержит последний дочерний узел данного узла, не являющийся атрибутом. Только чтение.
nextSibling Содержит следующий узел (любого типа) на том же уровне данного узла. Только чтение.
previousSibling Содержит предыдущий узел (любого типа) на том же уровне данного узла. Только чтение.
parentNode Содержит узел, для которого данный узел является дочерним (не действует для атрибутов). Только чтение.
ownerDocument Содержит корневой узел документа, содержащего данный узел. Только чтение.
text Содержит всё текстовое содержимое данного узла, включая подчинённые узлы. Чтение и запись.
xml Содержит всё xml-содержимое данного узла, включая подчинённые узлы. Только чтение.
nodeValue Содержит значение данного узла. Если компонент XML непосредственно не имеет значения, содержит null. Чтение и запись.
getElementsByTagName(typename) Возвращает коллекцию XMLDOMNodeList всех элементов заданного типа. Если указано "*", возвращает все элементы.
attributes Содержит коллекцию XMLDOMNamedNodeMap всех дочерних узлов-атрибутов данного узла. Только чтение.
getAttribute(name) Возвращает значение атрибута с заданным именем.
getAttributeNode(name) Возвращает узел атрибута с заданным именем.

Свойства и методы объекта-коллекции XMLDOMNodeList:

Описание
length Количество элементов (узлов) в коллекции.
item(index) Возвращает узел по заданному индексу. Отсчёт начинается с нуля. Данный метод является методом по умолчанию.
reset() Устанавливает внутренний указатель на позицию перед первым узлом в наборе, чтобы следующий вызов nextNode() возвращал первый узел.
nextNode() Возвращает следующий узел в наборе, в соответствии с позицией внутреннего указателя.

Коллекция XMLDOMNamedNodeMap помимо свойств и методов коллекции XMLDOMNodeList поддерживает методы:

Описание
getNamedItem(strName) Возвращает узел, соответствующий атрибуту с заданным именем.
setNamedItem(newItem) Добавляет переданный узел-атрибут в коллекцию (если атрибут с таким именем уже есть, замещает).

Перебор наименований товаров из образцового XML-документа:

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Получаем корневой элемент (элемент PRODUCTS)
Set currNode = xmlParser.documentElement
'Получаем первый товар (элемент PRODUCT)
Set currNode = currNode.firstChild
'Перебор всех товаров (элементов PRODUCT)
While Not currNode Is Nothing
	'Первый дочерний элемент товара - элемент TITLE,
	'выводим его содержимое
	WScript.Echo currNode.childNodes(0).text
	'Содержимое дочернего узла типа "text" элемента TITLE -
	'ещё один способ вывода наименования товара
	WScript.Echo currNode.childNodes(0).childNodes(0).nodeValue
	'Переходим к следующему товару (элементу PRODUCT)
	Set currNode = currNode.nextSibling
Wend

Ещё один способ перебора наименований товаров из образцового XML-документа (используем коллекцию XMLDOMNodeList):

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Получаем все заголовки товаров (элементы "TITLE")
Set colNodes = xmlParser.getElementsByTagName("TITLE")
'Устанавливаем внутренний указатель на позицию перед первым узлом в наборе
colNodes.reset
'Получаем первый заголовок (узел "TITLE")
Set nodeTitle = colNodes.nextNode
'Перебираем все заголовки (узлы "TITLE")
While Not nodeTitle Is Nothing
	WScript.Echo nodeTitle.text
	Set nodeTitle = colNodes.nextNode
Wend

Работаем с атрибутами. Выводим наименования только импортных товаров из образцового XML-документа:

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Получаем все товары (элементы "PRODUCT")
Set colNodes = xmlParser.getElementsByTagName("PRODUCT")
'Перебираем все товары
For Each nodeProduct In colNodes
	'Если товар импортный, выводим его наименование
	If nodeProduct.getAttribute("import")="yes" Then
		WScript.Echo nodeProduct.childNodes(0).text
	End If
Next

Рекурсивный обход всего дерева элементов. Этот скрипт будет работать для любого XML-документа, в т.ч. для XSL-таблицы стилей, приведённой выше непосредственно после нашего "каталога товаров":

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Запускаем рекурсию с корневого элемента (нулевой уровень)
ParseNode xmlParser.documentElement, 0
'******************************************************************************
Function ParseNode(nodeNode, numLevel)
	'Выводим имя узла, а также его значение, если оно есть
	If Not IsNull(nodeNode.nodeValue) Then
		WScript.Echo Space(numLevel*4) & nodeNode.nodeName & " = " & _
		             Trim(nodeNode.nodeValue)
	Else
		WScript.Echo Space(numLevel*4) & nodeNode.nodeName
	End If
	'Выводим атрибуты узла, если они есть
	If Not nodeNode.attributes Is Nothing Then
		For Each nodeAttr In nodeNode.attributes
			WScript.Echo Space((numLevel+1)*4) & nodeAttr.nodeName & _
			             " = " & nodeAttr.nodeValue
		Next
	End If
	'Выводим рекурсивно дочерние узлы, если они есть
	If nodeNode.childNodes.length > 0 Then
		For Each nodeChild In nodeNode.childNodes
			ParseNode nodeChild, numLevel+1
		Next
	End If
End Function

Получение информации о текущем узле дерева XML-документа

Перечень свойств:

Описание
nodeName Содержит полное имя данного узла, включая префикс пространства имён. Только чтение.
baseName Содержит имя данного узла без префикса пространства имён. Только чтение.
prefix Содержит префикс (пространства имён) имени данного узла. Только чтение.
nodeType Содержит тип текущего узла (число). Только чтение. Возможные значения:
  • NODE_ELEMENT(1) - элемент.
  • NODE_ATTRIBUTE(2) - атрибут.
  • NODE_TEXT(3) - текст.
  • NODE_CDATA_SECTION(4) - раздел CDATA.
  • NODE_ENTITY_REFERENCE(5) - примитив (ссылка в тексте).
  • NODE_ENTITY(6) - объявление примитива.
  • NODE_PROCESSING_INSTRUCTION(7) - инструкция по обработке.
  • NODE_COMMENT(8) - комментарий.
  • NODE_DOCUMENT(9) - корневой элемент документа.
  • NODE_DOCUMENT_TYPE(10) - описание типа документа (DTD).
  • NODE_DOCUMENT_FRAGMENT(11) - фрагмент XML-документа (несвязанное поддерево).
  • NODE_NOTATION(12) - нотация.
nodeTypeString Содержит тип текущего узла (строка строчными буквами). Только чтение.
dataType Содержит тип данных узла-атрибута, если этот тип данных определён в DTD. Чтение и запись.
namespaceURI Содержит URI пространства имён текущего узла. Только чтение.
definition Для узла типа "entityreference" содержит узел типа "entity" (т.е. его DTD-определение). Только чтение.

Рекурсивный обход всего дерева элементов с выводом информации о текущем узле. Этот скрипт будет работать для любого XML-документа, в т.ч. для XSL-таблицы стилей, приведённой выше непосредственно после нашего "каталога товаров":

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Запускаем рекурсию с корневого элемента (нулевой уровень)
ParseNode xmlParser.documentElement, 0
'******************************************************************************
Function ParseNode(nodeNode, numLevel)
	'Выводим данные об узле
	WScript.Echo Space(numLevel*4) & nodeNode.nodeName & _
	             " (baseName = " & nodeNode.baseName & "," & _
	             " prefix = " & nodeNode.prefix & ")"
	WScript.Echo Space(numLevel*4) & "(nodeType = " & nodeNode.nodeType & "," & _
	             " nodeTypeString = " & nodeNode.nodeTypeString & ")"
	WScript.Echo Space(numLevel*4) & "(dataType = " & nodeNode.dataType & "," & _
	             " namespaceURI = " & nodeNode.namespaceURI & ")"
	'Выводим рекурсивно атрибуты узла, если они есть
	If Not nodeNode.attributes Is Nothing Then
		For Each nodeChild In nodeNode.attributes
			ParseNode nodeChild, numLevel+1
		Next
	End If
	'Выводим рекурсивно дочерние узлы, если они есть
	If nodeNode.childNodes.length > 0 Then
		For Each nodeChild In nodeNode.childNodes
			ParseNode nodeChild, numLevel+1
		Next
	End If
End Function

Поиск и отбор узлов

Перечень методов:

Описание
selectNodes(patternString) Возвращает коллекцию XMLDOMNodeList, содержащую поддерево, выбранное по шаблону поиска patternString.
selectSingleNode(patternString) Аналогичен методу selectNodes, но возвращает только первый узел из выбранного поддерева.

В качестве параметра вышеуказанные методы принимают строку XSL-запроса (образец поиска - XSL pattern). Язык XSL-запросов напоминает способ определения пути в файловой системе - это список узлов, разделённых символом "/". Для указания на текущий элемент используется символ ".", на родительский - "..", для указания на все дочерние элементы - символ "*", для указания на элемент, расположенный ниже по дереву (не важно, на каком уровне вложенности) - символы "//". Условия в запросе заключаются в квадратные скобки "[" и "]". Имена атрибутов в запросе должны предваряться символом "@".

Вот примеры простейших запросов к образцовому XML-документу, расположенному в начале статьи:

Выберем из образцового XML-документа и отобразим наименования отечественных товаров, у которых есть сорт серого цвета, а также всех импортных товаров:

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Выбираем заголовки (элементы TITLE) тех товаров,
'которые отвечают заданным условиям
Set colNodes = _
    xmlParser.selectNodes("//PRODUCT[(@import='no' and SORT/COLOR = 'gray')" & _
    " or (@import='yes')]/TITLE")
'Перебираем полученную выборку
For Each nodeNode In colNodes
	WScript.Echo nodeNode.text
Next

Вот запрос, составленный по-другому, но возвращающий те же результаты:

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Выбираем заголовки (элементы TITLE) тех товаров,
'которые отвечают заданным условиям
Set colNodes = _
    xmlParser.selectNodes("//TITLE[(../@import='no' and ../SORT/COLOR='gray')" & _
    " or (../@import='yes')]")
'Перебираем полученную выборку
For Each nodeNode In colNodes
	WScript.Echo nodeNode.text
Next

Ещё один способ выборки, с использованием метода selectSingleNode:

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Выбираем товары, которые отвечают заданным условиям
Set colNodes = _
    xmlParser.selectNodes("//PRODUCT[(@import='no' and SORT/COLOR = 'gray')" & _
    " or (@import='yes')]")
'Перебираем полученную выборку
For Each nodeNode In colNodes
	Set nodeTitle = nodeNode.selectSingleNode("TITLE")
	WScript.Echo nodeTitle.text
Next

Создание, модификация и запись XML-документов

Перечень методов:

Описание
save(objTarget) Сохраняет документ в файле (если указан URL) или замещает содержимое другого документа (если указан объект XMLDOMDocument).
createElement(tagName) Создаёт и возвращает элемент с указанным именем.
createAttribute(name) Создаёт и возвращает новый атрибут с указанным именем.
createCDATASection(strData) Создаёт и возвращает новый узел CDATA, содержащий переданное значение.
createProcessingInstruction(strTarget, strData) Создаёт и возвращает новый узел инструкции по обработке.
createComment(strComment) Создаёт и возвращает новый узел комментария.
createEntityReference(strName) Создаёт и возвращает новый узел ссылки на примитив.
createTextNode(strText) Создаёт и возвращает новый текстовый узел.
createNode(numType, strName, strNamespaceURI) Универсальный метод - создаёт и возвращает новый узел указанного типа и названия. Позволяет использовать пространства имён.
createDocumentFragment() Создаёт и возвращает новый пустой фрагмент XML-документа, который в дальнейшем можно "наполнить" узлами и присоединить к XML-документу.
cloneNode(boolDeep) Создаёт и возвращает копию текущего узла. Параметр boolDeep определяет, нужно ли рекурсивно копировать дочерние элементы.
setAttribute(name, value) Устанавливает значение указанного атрибута текущего узла. При необходимости создаёт атрибут.
setAttributeNode(AttributeNode) Устанавливает или обновляет переданный атрибут у текущего элемента.
removeAttribute(name) Удаляет указанный атрибут. Если указанный атрибут имеет значение по умолчанию, вместо удаления происходит замещение: атрибуту просто устанавливается значение по умолчанию.
removeAttributeNode(nodeAttribute) Удаляет переданный объект узла-атрибута. Если этот атрибут имеет значение по умолчанию, вместо удаления происходит замещение: атрибуту просто устанавливается значение по умолчанию.
appendChild(newChildNode) Добавляет текущему узлу новый дочерний элемент и возвращает ссылку на этот элемент. То же самое можно сделать вызовом insertBefore(newChildNode, null).
insertBefore(newChildNode, refChildNode) Вставляет новый дочерний узел (newChildNode) перед указанным существующим дочерним узлом (refChildNode). Если последний параметр не задан, новый дочерний узел будет добавлен в конец.
replaceChild(newChildNode, oldChildNode) Заменяет указанный дочерний объект текущего элемента на новый и возвращает старый дочерний объект. Если новый дочерний объект - null, старый дочерний объект будет просто удалён.
removeChild(childNode) Удаляет указанный дочерний объект текущего элемента и возвращает его.

Все методы, которые создают новые объекты (createElement, createAttribute и подобные) не выполняют никакой работы, кроме непосредственно самого создания объектов. Для включения созданных объектов в документ надо дополнительно вызывать методы appendChild, insertBefore и подобные.

Пример создания нового XML-документа:

Set xmlParser = CreateObject("Msxml2.DOMDocument")

'Создание объявления XML
xmlParser.appendChild(xmlParser.createProcessingInstruction("xml", "version='1.0' encoding='windows-1251'"))
'Создание комментария
xmlParser.appendChild(xmlParser.createComment("Текст комментария"))
'Создание корневого элемента
Set rootNode = xmlParser.appendChild(xmlParser.createElement("ROOT"))

'Создание первого вложенного элемента
Set subNode = rootNode.appendChild(xmlParser.createElement("SUB"))
subNode.text = "Текст первого вложенного элемента"

'Создание второго вложенного элемента
Set subNode = rootNode.appendChild(xmlParser.createElement("SUB"))
'Создание раздела CDATA
subNode.appendChild(xmlParser.createCDATASection("<<< >>> &&& Произвольные текстовые данные"))
'Создание ссылки на примитив
subNode.appendChild(xmlParser.createEntityReference("amp"))
'Создание текстового узла
subNode.appendChild(xmlParser.createTextNode("Текст второго вложенного элемента"))

'Создание третьего вложенного элемента с использованием пространства имён
Set subNode = rootNode.appendChild(xmlParser.createNode(1, "html:H1", "http://www.w3c.org/TR/REC-html40/"))
subNode.text = "Заголовок HTML"

'Создание четвёртого и пятого вложенных элементов с использованием фрагмента
Set Fragment = xmlParser.createDocumentFragment
Fragment.appendChild(xmlParser.createElement("SUB"))
Fragment.appendChild(xmlParser.createElement("SUB"))
rootNode.appendChild(Fragment)

xmlParser.save("C:\Test.xml")

Добавим новый товар в начало нашего существующего "каталога товаров":

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Получаем корневой элемент
Set rootPRODUCTS = xmlParser.documentElement
'Получаем первый товар
Set firstPRODUCT = xmlParser.documentElement.childNodes(0)
'Вставляем новый товар перед первым
Set newPRODUCT = rootPRODUCTS.insertBefore(xmlParser.createElement("PRODUCT"), firstPRODUCT)
'Устанавливаем атрибут "import" для нового товара
Set newAttr = xmlParser.createAttribute("import")
newAttr.value = "yes"
newPRODUCT.setAttributeNode(newAttr)
'Добавляем наименование новому товару
Set newTITLE = newPRODUCT.appendChild(xmlParser.createElement("TITLE"))
newTITLE.text = "Product #0"
'Добавляем сорт новому товару
Set newSORT = newPRODUCT.appendChild(xmlParser.createElement("SORT"))
'Добавляем цвет сорту
Set newCOLOR = newSORT.appendChild(xmlParser.createElement("COLOR"))
newCOLOR.text = "navy"
'Добавляем цену сорту
Set newPRICE = newSORT.appendChild(xmlParser.createElement("PRICE"))
newPRICE.text = "$0.01"
'Сохраняем весь документ
xmlParser.save("C:\Sample.xml")

Добавим новый товар в начало нашего существующего "каталога товаров" с помощью копирования:

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Получаем корневой элемент
Set rootPRODUCTS = xmlParser.documentElement
'Получаем первый товар
Set firstPRODUCT = xmlParser.documentElement.childNodes(0)
'Вставляем копию первого товара перед первым товаром
Set newPRODUCT = rootPRODUCTS.insertBefore(firstPRODUCT.cloneNode(True), firstPRODUCT)
'Устанавливаем атрибут "import" для нового товара
newPRODUCT.setAttribute "import", "yes"
'Сохраняем документ
xmlParser.save("C:\Test.xml")

Меняем местами, удаляем товары:

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Получаем корневой элемент
Set rootPRODUCTS = xmlParser.documentElement
'Получаем копии первого и второго товаров
Set firstPRODUCT = rootPRODUCTS.childNodes(0).cloneNode(True)
Set secondPRODUCT = rootPRODUCTS.childNodes(1).cloneNode(True)
'Меняем местами первый и второй товары
rootPRODUCTS.replaceChild secondPRODUCT, rootPRODUCTS.childNodes(0)
rootPRODUCTS.replaceChild firstPRODUCT, rootPRODUCTS.childNodes(1)
'Удаляем последний товар
rootPRODUCTS.removeChild rootPRODUCTS.lastChild
'Сохраняем документ
xmlParser.save("C:\Test.xml")

Обработка поддеревьев стилевыми таблицами

Перечень методов:

Описание
transformNode(objStylesheet) Назначает стилевую таблицу для текущего узла и возвращает строку - результат обработки. Текущим узлом может быть весь XML-документ.
transformNodeToObject(objStylesheet, objXMLDOMDocument) То же, что и transformNode, но результат не возвращается, а помещается в objXMLDOMDocument.

Применяем существующую стилевую таблицу к каталогу товаров:

'Загружаем документ
Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Загружаем стилевую таблицу
Set objStylesheet = CreateObject("Msxml2.DOMDocument")
objStylesheet.async = False
objStylesheet.load "C:\Sample.xsl"
'Применяем стилевую таблицу к документу
WScript.Echo xmlParser.transformNode(objStylesheet)

Вывод товаров в обратном порядке с помощью XSL-сортировки:

'Загружаем документ
Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Загружаем стилевую таблицу
Set objStylesheet = CreateObject("Msxml2.DOMDocument")
objStylesheet.async = False
objStylesheet.loadXML _
"<?xml version='1.0' encoding='windows-1251'?>" & _
"<xsl:stylesheet xmlns:xsl='http://www.w3.org/TR/WD-xsl'>" & _
vbCrLf & _
"<xsl:template match='/'>" & _
"<PRODUCTS>" & _
"<xsl:apply-templates select='PRODUCTS/PRODUCT' order-by='-TITLE' />" & _
"</PRODUCTS>" & _
"</xsl:template>" & _
vbCrLf & _
"<xsl:template match='PRODUCT'>" & _
"<PRODUCT>" & _
"<xsl:value-of select='TITLE' />" & _
"</PRODUCT>" & _
"</xsl:template>" & _
vbCrLf & _
"</xsl:stylesheet>"
'Применяем стилевую таблицу к документу
Set objResult = CreateObject("Msxml2.DOMDocument")
objResult.async = False
xmlParser.transformNodeToObject objStylesheet, objResult
'Выводим результаты
For Each nodeNode In objResult.documentElement.childNodes
	WScript.Echo nodeNode.text
Next

Прочие свойства и методы

Перечень свойств и методов:

Описание
doctype Содержит объект XMLDOMDocumentType (узел DTD XML-документа). Только чтение. Если DTD в документе отсутствует, свойство содержит null. Только чтение.
url Содержит URL документа. Только чтение.
nodeFromID(idString) Возвращает узел по значению его атрибута типа ID (т.е. осуществляет поиск узла по ID) или Nothing, если узел не найден.
hasChildNodes() Возвращает True, если текущий узел имеет дочерние узлы, и False в противном случае.
specified Возвращает True, если текущий узел атрибута явно определён в тексте документа, и False в противном случае (если атрибут опущен и имеет значение по умолчанию, взятое из DTD).
normalize() Нормализует все текстовые узлы элемента (на любой глубине), объединяя два или больше смежных текстовых узла в один текстовый узел.

Примеры использования некоторых свойств и методов:

Set xmlParser = CreateObject("Msxml2.DOMDocument")
xmlParser.async = False
xmlParser.load "C:\Sample.xml"
'Отображаем DTD документа
WScript.Echo xmlParser.doctype.xml
'Отображаем URL документа
WScript.Echo xmlParser.url
'Проверяем, имеет ли корневой узел документа дочерние узлы
If xmlParser.documentElement.hasChildNodes Then
	WScript.Echo "Узел " & xmlParser.documentElement.nodeName & " имеет дочерние узлы."
End If
'Проверяем, у каких товаров (элементов "PRODUCTS") явно задан атрибут "import"
For Each nodePRODUCT In xmlParser.documentElement.childNodes
	strTitle = nodePRODUCT.getElementsByTagName("TITLE")(0).text
	If nodePRODUCT.attributes(0).specified Then
		WScript.Echo "У товара '" & strTitle & "' атрибут 'import' задан явно - " & _
		             nodePRODUCT.getAttribute("import")
	Else
		WScript.Echo "У товара '" & strTitle & "' атрибут 'import' опущен - " & _
		             nodePRODUCT.getAttribute("import")
	End If
Next

Людоговский Александр

Перейти на главную страничку сайта (список статей, файлы для скачивания)

© 2007 http://www.script-coding.com При любом использовании материалов сайта обязательна ссылка на него как на источник информации, а также сохранение целостности и авторства материалов.