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

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

   Одним из доступных на сегодня DOM-совместимых наборов классов для работы с документами является библиотека com.ibm.dom, входящая в состав XML анализатора xml4j от IBM. Получить ее можно по адресу 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 ");



    } 



}

   Комментарии

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

Назад | Содержание

 

Используются технологии uCoz