DOM совместимые анализаторы (XML)

Автор: Topol Понедельник, Апрель 16th, 2012 Нет комментариев

Рубрика: Программирование

Другим способом представления внутренней структуры документа являются DOM — интерфейсы. Как уже упоминалось, их реализацией занимаются разработчики XML-анализатора, используя для этого возможности конкретного языка программирования. Программисты на Java могут найти эти классы в библиотеке org.w3.dom. Наследуя виртуальные методы DOM интерфейсов, классы анализатора предоставляют приложению стандартный способ манипулирования структурой документа. В свою очередь, приложение, использующее XML-анализатор, может не знать о способе реализации интерфейсов, ему доступна готовая библиотека методов, при помощи которой он может производить поиск нужных фрагментов документа, создавать, удалять и модифицировать его элементы.

Одним из доступных на сегодня DOM-совместимых наборов классов для работы с документами является библиотека com.ibm.dom, входящая в состав XML анализатора xml4j от IBM. Получить ее можно по адресу http://www.alphaworks.ibm.com/. Принцип использования DOM интерфесов по сравнению с IE5 практически не изменился — поменялись только названия объектов и методов. Их краткий обзор представлен в следующей таблице.

Node Базовый интерфейс для остальных элементов объектной модели XML, представляющий узел дерева структуры документа.
Document Используется для получения информации о документе и изменения его структуры. Это интерфейс представляет собой корневой элемент XML документа и содержит методы доступа ко всему содержимому документа. При помощи методов объекта Document в программе можно создавать дочерние объекты, представляющие различные конструкции документа (например, createElement — создание элемента, createComment — создание комментария, createTextNode — текстового фрагмента), удалять, перемещать, добавлять объекты (removeChild, replaceChild, insertBefore, …), перемещаться по дереву элементов(getFirstChild, getLastChild, getNextSibling, getParentNode, getPreviousSibling, …), получать элементы по их названию (getElementsByTagName,) и т.д. В объектной модели IE5 этот интерфейс доступен для сценариев на JScript, VB через объект XMLDOMDocument
Element Представляет элемент документа, определяя методы доступа к его названию(getTagName, getElementsByTagName), атрибутам (getAttribute, getAttributeNode, setAttribute, removeAttribute, : ) и дочерним элементам(appendChild, getChildNodes, getFirstChild, …).
Attr Интерфейс, представляющий атрибут элемента. Имеет методы для получения(getValue) и установления(setValue) значения атрибута. Хотя согласно синтаксису XML атрибуты должны назначаться только элементам, в DOM возможно их создание любым объектом, наследующим интерфейс Node. Поэтому можно создать атрибут для документа, который будет находится в списке атрибутов, но не принадлежать ни одному из его элементов.
CharacterData Интерфейс, предоставляющий доступ к текстовым данным документа. В XML документе к этому типу данных относятся комментарии, текстовое содержимое элементов, секции CDATA. При помощи методов этого интерфейса можно добавлять, удалять, редактировать данные(appendData, deleteData, replaceData, setData), получать размер области текста (getLength) и извлекать текстовое содержимое(getData, substringData, …)
Comments Интерфейс для доступа к тексту комментариев
Text Представляет текстовое содержимое элемента
CDATASection Интерфейс, представляющий секции CDATA — фрагментов документа, заключенные в символы «[[" и "]]>», которые не обрабатываются XML-анализатором и поэтому могут содержать символы, «запрешенные» в спецификации XML. В эту область можно, к примеру, помещать стилевые таблицы или JavaScript сценарии, используемые при отображении HTML страницы.
ProcessingInstruction Предоставляет доступ к т.н. области «инструкций процессора», данные из которой используются XML-анализатором при разборе документа. Доступ к этим данным возможен при помощи методо getData, setData и getTarget
Notation Определяет инструкцию DTD описания. Для получения ее идентификаторов используются методы getPublicId и getSystemId . DOM Level 1 не поддерживает прямого доступа к DTD декларациям по записи и сейчас они доступны лишь для чтения (при помощи параметра nodeName интерфейса Node)

В следующем примере демонстрируется использование DOM-объектов для вывода содержимого XML документа в двух форматах — в виде дерева элементов и обычной HTML страницы. Немного изменив пример, можно заставить программу сохранять выходной формат в файле и мы получим таким образом обычный XML-HTML конвертор.

/*
Пример использования DOM анализатора.
Демонстрируется возможность рекурсивного обхода дерева элементов,
создание новых элементов, фильтрация элементов (поиска по параметрам)
*/

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.*;

import org.w3c.dom.*;

import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.ParserFactory;

import com.ibm.xml.parsers.DOMParser;

public class logParser {

static String defaultParser = «com.ibm.xml.parsers.DOMParser»;
static String urlLog;
static  Document xmldoc = null;
static  PrintWriter out;

/*
Конструктор нашего класса- обработчика.
В нем создается выходной поток для печати
*/

public logParser(String url){
urlLog = url;

try {
out = new PrintWriter(new OutputStreamWriter(System.out, «koi8-r»));
}
catch (UnsupportedEncodingException e) {
System.err.println(e.toString());
}

}

public void parseDoc(){
parseDoc(defaultParser);
}

/*
Создание класса анализатора, обрабтка им XML-документа
и создание объектной модели документа
*/

public void parseDoc(String parserName){

try {
Parser parser = ParserFactory.makeParser(parserName);
parser.parse(urlLog);

// Получение указателя на корневой элемент документа
xmldoc = ((DOMParser)parser).getDocument();

}
catch (Exception e) {
System.err.println(e.toString());
}
}

//==========================================================================
// Вывод содержимого документа в виде форматированного списка XML- элементов
//========================

public void viewLogAsXML(){

try {

viewLogAsXML(xmldoc,»");

}
catch (Exception e) {
System.out.println(e.toString());
}
out.flush();

}

/*
Рекурсивный обход элементов документа, начиная с указанного
элемента node.
*/

public void viewLogAsXML(Node node,String offs){

if (node == null) {
return;
}
int type = node.getNodeType();
// Получение информации о типе текущего узла
switch (type) {
/* Если текщий узел — корневой элемент документа */

case Node.DOCUMENT_NODE: {
out.println(«<?xml version=\»1.0\» encoding=\»koi-8\»?>»);
viewLogAsXML(((Document)node).getDocumentElement(),offs);
out.flush();
break;
}

/* Если текщий узел — элемент */

case Node.ELEMENT_NODE: {
out.print(offs+»<»);
// Печать названия элемента
out.print(node.getNodeName());
// Получение списка атрибутов текущего элемента

NamedNodeMap attrs = node.getAttributes();
Node attr;
for (int i = 0; i < attrs.getLength(); i++) {
attr = attrs.item(i);
out.print(‘ ‘);
out.print(attr.getNodeName()+»=\»"+attr.getNodeValue()+»\»");
}
out.println(‘>’);

// Получение списка дочерних элементов
NodeList children = node.getChildNodes();

// Если у текщего элемента есть дочерние, то выводим и их

if (children != null) {
int len = children.getLength();
for (int i = 0; i < len; i++) {
viewLogAsXML(children.item(i),offs+» «);
}
}
break;
}

/* Если текщий узел — текстовый */
case Node.TEXT_NODE: {
out.println(offs+node.getNodeValue());
break;
}

}
// Печать закрывающего тэга элемента
if (type == Node.ELEMENT_NODE) {
out.print(offs+»</»);
out.print(node.getNodeName());
out.println(‘>’);
}

}

//=======================================================
// Вывод в формате HTML
//=====================

/* Вызов рекурсивного обходчика */

public void viewLog(){

// Header
viewAsHTML(«All log records:»);

try {

// Вывод содержимого
viewLog(null);

}
catch (Exception e) {
System.out.println(e.toString());
}

// Header
viewAsHTML();

}

/* Печать только сообщений об ошибках */

public void viewErrors(){

// Header
viewAsHTML(«Log errors:»);

try {
// Вывод содержимого
viewLog(«error»);
}
catch (Exception e) {
System.out.println(e.toString());
}
// Footer
viewAsHTML();

}

/*
Рекурсивный обход элементов, у которых атрибут type равен заданному.
*/

public int viewLog(String type){

int i=0;
int elemNum=0;
int messageCount=0;
Element elem;
NodeList elements;

elements = xmldoc.getElementsByTagName(«event»);
if(elements==null) System.out.println(«Empty element collection»);

elemNum = elements.getLength();

if (type == null) {

for (i = 0; i < elemNum; i++) {
if(elements.item(i)==null) System.out.println(«Empty element»);
viewLogMessage((Element)elements.item(i));
}
messageCount=elemNum;

}
else {
for (i = 0; i < elemNum; i++) {
elem = (Element)elements.item(i);

if(elem.getAttribute(«type»)==type){
messageCount++;
viewLogMessage(elem);
}

}
}
return messageCount;
}

/* Печать заголовка таблицы */

public void viewAsHTML(String title){
out.println(«<html>»);
out.println(«<head><title>Log parser sample</title></head>»);
out.println(«<body><br><b>»+title+»</b><hr>»);
out.println(«<table cellspacing=\»2\» cellpadding=\»2\» border=\»1\»
width=\»600\»>»);
out.println(«<tr bgcolor=\»silver\»><th>IP</th><th>Date</th><th>Method</th>
<th>Request</th><th>Response</th></tr>»);
}

/* Печать комментариев к таблице */

public void viewAsHTML(){
Date d = new Date();
String date = new String
(
«»+d.getHours()+»:»+d.getMinutes()+»:»+d.getSeconds()
);
out.println(«</table><hr>generated by logParser at <i>»+date+»</i><br>
</body></html>»);
out.flush();
}

/* Форматированный вывод содержимого элемента event */

public void viewLogMessage(Element elem){

/*
Получение текста внутри элемента — обращаемся к первому
дочернему узлу (им должен оказаться текст) и получаем его
значение, используя метод getNodeValue() интерфейса Node
*/

String str_from=(elem.getElementsByTagName
(«ip-from»)).item(0).getFirstChild().getNodeValue();
String str_method=(elem.getElementsByTagName
(«method»)).item(0).getFirstChild().getNodeValue();
String str_to=(elem.getElementsByTagName
(«url-to»)).item(0).getFirstChild().getNodeValue();
String str_result=(elem.getElementsByTagName
(«response»)).item(0).getFirstChild().getNodeValue();

out.println(«<tr><td>»+str_from+»</td><td>»+elem.getAttribute(«date»)+»</td>
<td>»+str_method+»</td><td>»+str_to+»</td><td>»+str_result+»</td></tr>»);

}

//=======================================================
// Модификация дерева элементов
//=============================

public void logMessage(String result, String datetime, String method, String
ipfrom, String urlto, String response){

if(xmldoc==null) return;

Element root = xmldoc.getDocumentElement();
Element log_elem = xmldoc.createElement(«event»);
log_elem.setAttribute(«result»,result);
log_elem.setAttribute(«date»,datetime);

Element elem;
Text elem_value;

elem = xmldoc.createElement(«method»);
elem_value = xmldoc.createTextNode(method);
elem.appendChild(elem_value);
log_elem.appendChild(elem);

elem = xmldoc.createElement(«ip-from»);
elem_value = xmldoc.createTextNode(ipfrom);
elem.appendChild(elem_value);
log_elem.appendChild(elem);

elem = xmldoc.createElement(«url-to»);
elem_value = xmldoc.createTextNode(urlto);
elem.appendChild(elem_value);
log_elem.appendChild(elem);

elem = xmldoc.createElement(«response»);
elem_value = xmldoc.createTextNode(response);
elem.appendChild(elem_value);
log_elem.appendChild(elem);

root.appendChild(log_elem);
}

//=======================================================
// Пример использования методов класса logParser
//==============================================

public static void main(String argv[]) {

/*
Создание объекта анализатора. В качестве параметра ему
передается название документа(можно и через командную строку, конечно…)
*/

logParser log_file = new logParser(«log.xml»);
log_file.parseDoc();                            // Анализ документа

if (argv.length == 0) {                       // Что с ним делать
log_file.viewLogAsXML();
System.exit(0);
}

for (int i = 0; i < argv.length; i++) {
String arg = argv[i];

if (arg.startsWith(«-»)) {
if (arg.equals(«-vx»)) {
log_file.viewLogAsXML();
break;
}
if (arg.equals(«-va»)) {
log_file.viewLog();
break;
}
if (arg.equals(«-ve»)) {
log_file.viewErrors();
break;
}

if (arg.equals(«-h»)) {
usage();
}
}
}

log_file.logMessage(«success»,»12″,»GET»,»127.0.0.1″,»./index.html»,»200″);
log_file.viewLogAsXML();

}
private static void usage() {

System.err.println(«usage: java logParser (options)»);
System.err.println();
System.err.println(«options:»);
System.err.println(«  -vx View result as XML tree (default)»);
System.err.println(«  -va View all messages as HTML page»);
System.err.println(«  -ve View only errors as HTML page»);
System.err.println(«  -h  View help «);

}

}

Комментарии

Более подробные комментарии, файлы приложений и результатов их работы можно найти по адресу http://www.mrcpk.nstu.ru/

Источник: webcorp.ru

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты