Rambler's Top100IT • archiv

rus / eng | Логин | Комментарий к колонке | Печать | Почта | Клуб




Колонки


Использование Java XML-обработчиков

 
(Александр Печерский)

Использование Java XML-обработчиков

   Internet Explorer, несмотря на мощную встроенную поддержку XML, сегодня далеко не единственное средство, которое можно использовать для работы с новым языком. Обработкой XML документа на стороне клиента или сервера может также заниматься любой другой анализатор XML-документов, который конвертирует их в обычную HTML страницу или извлекает из нее информацию для других приложений.

   Что такое XML Parser?

   Любой XML-процессор, являясь, по сути, транслятором языка разметки, может быть разбит на несколько модулей, отвечающих за лексический, синтаксический и семантический анализ содержимого документа. Понятно, что если бы мы были вынуждены каждый раз писать все эти блоки самостоятельно, необходимость в XML как в таковом бы отпала - основное его преимущество, как уже упоминалось ранее, заключается в стандартном способе извлечения информации из документа. Синтаксически правильно составленный XML-документ может быть разобран любым универсальным XML анализатором, и нашему XML-обработчику остается лишь использовать полученные на его выходе "чистые" данные (прошедшие синтаксический анализ) - интерпретировать содержимое документа, в соответствии с его DTD-описанием или схемами данных.

Рис. 2 Иллюстрация механизма доступа к содержимому XML-документа при помощи интерфейсов анализатора

   Конечно, синтаксический анализатор может быть довольно легко реализован и самостоятельно, например, в Perl, с его мощными возможностями обработки регулярных выражений. Но в общем случае такой "ручной" способ является довольно нетривиальной задачей, требующей некоторых усилий и является дополнительным источником ошибок. Поэтому применение универсальных XML-анализаторов может существенно облегчить жизнь разработчикам, тем более, что уже сегодня количество свободно доступных программ такого рода довольно велико.

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

   Описывая разобранный XML-документ, универсальная программа-анализатор должна представить его структуру в виде упорядоченной модели данных, для доступа к которой используется какая-то станадртная, описанная в соответствующей спецификации библиотека классов - интерфейсов XML документа. На сегодняшний день существует два подхода к их построению: собыйтийный - Simple API for XML, SAX и объектно-ориентированный - DOM(Document Object Model). Рассмотрим их использование на конкретных примерах.

   Что такое SAX

   Сегодня стандартным интерфейсом для большинства универсальных XML-анализаторов является событийно-ориентированное API SAX - Simple API for XML.

   Термин событийно-ориентированный является ключевым в этом определении и объясняет способ использования SAX. Каждый раз, когда при разборе XML документа анализатор оказывается в каком-то новом состоянии - обнаруживает какую-либо синтаксическую конструкцию XML-документа (элемент, символ, шаблон, и т.д.), фиксирует начало, конец объявлений элементов документа, просматривает DTD-правила или находит ошибку, он воспринимает его как произошедшее событие и вызывает внешнюю процедуру - обработчик этого события. Информация о содержимом текущей конструкции документа передается ему в качестве параметров функции. Обработчик события - это какой-то объект приложения, который выполняет необходимые для обработки полученной из XML информации действия и осуществляет таким образом непосредственный разбор содержимого. После завершения этой функции управление опять передается XML-анализатору и процесс разбора продолжается.

   Реализацией этого механизма в Java SAX 1.0 является библиотека классов org.xml.sax (их можно получить, например, с узла: www.megginson.com, но обычно эти классы включаются в состав XML -анализатора). Наследуя клссы SAX-совместимого анализатора, мы получаем универсальный доступ к XML документу при помощи классов, содержимое и механизм использование которых приведено в соответствующем описании.

   Последовательный разбор XML-документа SAX-обработчиком обычно производится по следующей схеме (более подробное описание приведено ниже):

  • загрузить документ, установить обработчики событий, начать просмотр его содержимого (если есть DTD-описания, то - их разбор);
  • найдено начало документа (его корневой, самый первый элемент) - вызвать виртуальную функцию- обработчик события startDocument;
  • каждый раз, когда при разборе будет найден открывающий тэг элемента вызывается обработчик-функция startElement. В качестве параметров ей передаются название элемента и список его атрибутов;
  • найдено содержимое элемента - передать его соответствующему обработчику - characters, ignorableWhitespace,processingInstruction и т.д.;
  • если внутри текущего элемента есть подэлементы, то эта процедура повторяется;
  • найден закрывающий тэг элемента - обработать событие endElement();
  • найден закрывающий тэг корневого элемента -обработать событие endDocument;
  • если в процессе обработки были обнаружены ошибки, то анализатором вызываются обработчики предупреждений (warning), ошибок (error) и критических ошибок обработчика (fatalError).

   Ссылка на объект класса обработчика событий может передаваться объекту XML-анализатора при помощи следующих функций:

   parser.setDocumentHandler(event_class); // - обработчик событий документа

   parser.setEntityResolver(event_class); // - обработчик событий загрузки DTD-описаний

   parser.setDTDHandler(event_class); // - обработчик событий при анализе DTD-описаний

   parser.setErrorHandler(event_class); // - обработчик чрезвычайных ситуаций

   Здесь event_class - объект созданного нами ранее класса.

   Краткое описание некоторых из объектов-обработчиков событий приведено в следующей таблице:

   Объект DocumentHandler

startDocument()

Начало документа

endDocument()

Конец документа

startElement (String name, AttributeList atts)

Начало элемента. Функции передается название элемента(открывающий тэг) и список его атрибутов.

endElement (String name)

Конец элемента

characters (char[] cbuf, int start, int len)

Обработка массива текстовых символов

ignorableWhitespace (char[] cbuf, int start, int len)

Необрабатываемые символы

processingInstruction (String target, String data)

Обработка инструкций XML-анализатора)

   Объект ErrorHandler

warning (SAXParseException e)

Получение сообщения о "несерьезной" ошибке. Пдробная информация содержится в передаваемом объекте класса SAXParseException

error (SAXParseException e)

Сообщение об ошибке

fatalError (SAXParseException e)

Сообщение о критической ошибке

   Для демонстрции использования этих методов рассмотрим небольшой пример обработчика регистрационного XML-документа (его структура описана в примере 2 первого раздела статьи). Java-приложение выводит содержимое документа и информацию о его структуре, путь к документу задается в командной строке. Для компилирования потребуется JDK 1.1.4 и классы SAX, находящиеся либо в текущем пакете, либо вместе с другими классами в classes.zip.

Пример 1.

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

import com.ibm.xml.parsers.DOMParser;

import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.AttributeList;
import org.xml.sax.HandlerBase;
import org.xml.sax.helpers.ParserFactory;

class saxParser extends HandlerBase{

    private PrintWriter out;

    private int elements;
    private int attributes;
    private int characters;
    private int ignorableWhitespace;
    private String url;

    public saxParser(String url_str) {

        url = url_str;

        try {
            out = new PrintWriter(new OutputStreamWriter(System.out,
"koi8-r"));
        }
        catch (UnsupportedEncodingException e) {
        }

    }


//=======================================================
// Обработчики событий. Методы интерфейса DocumentHandler
//========================

    // Начало документа
    public void startDocument() {

    // Статистика
        elements            = 0;
        attributes          = 0;
        characters          = 0;
        ignorableWhitespace = 0;


    // Процессорные инструкции

    out.println("<?xml version=\"1.0\"
    encoding=\"UTF-8\"?>");

    }

    // Конец документа
    public void endDocument() {

        out.flush();

    }

// Встретился открывающий тэг элемента //

    public void startElement(String name, AttributeList attrs) {

        elements++;
        if (attrs != null) {
            attributes += attrs.getLength();
        }

      // Печать тэга элемента вместе со списком его атрибутов,
      // например, <elem id="48">
        out.print('<');
        out.print(name);
        if (attrs != null) {
            int len = attrs.getLength();
            for (int i = 0; i < len; i++) {
                out.print(' ');
                out.print(attrs.getName(i));
                out.print("=\"");
                out.print(attrs.getValue(i));
                out.print('"');
            }
        }
        out.println('>');


    }


// Встретился закрывающий тэг элемента

    public void endElement(String name) {

        out.println("</"+name+">");

    }

// Текстовые символы

    public void characters(char ch[], int start, int length) {

        characters += length;

        out.println(new String(ch, start, length));

    }

// Необрабатываемые символы(например, содержимое секции CDATA)

    public void ignorableWhitespace(char ch[], int start, int length) {

        characters(ch, start, length);

    }

// Инструкции XML-процессору

    public void processingInstruction (String target, String data) {

        out.print("<?");
        out.print(target);
        if (data != null && data.length() > 0) {
            out.print(' ');
            out.print(data);
        }
        out.print("?>");

    }

//===================================================
// Методы интерфейса ErrorHandler
//===============================

    // Последнее предупреждение
    public void warning(SAXParseException ex) {
        System.err.println("Warning at "+
                                ex.getLineNumber()+" . "+
                                ex.getColumnNumber()+"  -  "+
                                ex.getMessage());
    }

    // Произошла ошибка
    public void error(SAXParseException ex) {
        System.err.println("Error at {"+
                                ex.getLineNumber()+" . "+
                                ex.getColumnNumber()+"  -  "+
                                ex.getMessage());
    }

    // Такие ошибки исправить уже нельзя
    public void fatalError(SAXParseException ex) throws SAXException {
        System.err.println("Fatal error at {"+
                                ex.getLineNumber()+" . "+
                                ex.getColumnNumber()+"  -  "+
                                ex.getMessage());
        throw ex;
    }

//=======================================================
// Вывести информацию о документе
//===============================

    public void printInfo() {

        System.out.println();

        System.out.println("Документ "+url+"
        был успешно обработан");

        System.out.println("Элементов : "+elements);
        System.out.println("Атрибутов : "+attributes);
        System.out.println("Символов  : "+characters);

    }

}

//=======================================================
// Обработка XML документа
//========================

public class saxSample{

    public static void main(String argv[]) {

        try {
            saxParser sample = new saxParser(argv[0]);

            Parser parser = ParserFactory.makeParser
            ("com.ibm.xml.parsers.SAXParser");
            parser.setDocumentHandler(sample);
            parser.setErrorHandler(sample);

            parser.parse(argv[0]);
            sample.printInfo();
        }
        catch (Exception e) {
            e.printStackTrace(System.err);
        }

   }

}

   Комментарии

   Первым шагом в процессе построения XML-обработчика является создание объекта из класса анализатора (в нашем случае это классы из паекета com.ibm.xml.parsers). Для этого можно использовать класс ParserFactory, входящий в org.xml.sax.helpers:

import org.xml.sax.*;
...
Parser parser =
ParseFactory.createParser(); ...

   Затем следует определить обработчики возникающих в процессе разбора XML-документа событий. Приложению необязательно устанавливать все обработчики сразу - в классе HandlerBase все события могут обрабатываться "по умолчанию". Более подробную информацию по использованию SAX-анализаторов можно найти в примерах приложений в пакетах анализатора или на сервере www.megginson.com. Комментарии, файлы приложений и результатов их работы можно найти по адресу www.mrcpk.nstu.ru/xml/

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 конвертор.

Пример 2.

/*
Пример использования 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/




Справка | Условия Copyright © 1999 — 2008, IT • archiv.
В начало | Логин | Комментарий к колонке | Поиск | Почта