WebClub - Всероссийский Клуб Веб-разработчиков
 
 
Архив сайта WebClub.ru  /  ßçûêè ðàçìåòêè  /  XML Ссылки по теме
Здесь находится часть материалов старого сайта. Мы не планируем переносить в Архив все статьи: размещаются те материалы, сохранить которые нам показалось важным.
Язык 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 конвертор.

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

« предыдущая  |  содержание  |  следующая »


Если вы заняты в сфере веб-разработок, то вам также могут быть полезны следующие ресурсы:

Российские сайты:

  • PHP Club - один из старейших и самых живых веб-проектов Рунета, посвященный веб разработкам на PHP.
  • webmascon.com - журнал для веб-мастеров
  • XPoint.ru - форум профессиональных веб-разработчиков
  • ЦИТ-Форум
  • PHPFAQ.RU - название говорит само за себя. Очень часто задаваемые вопросы по РНР и ответы на них
  • Internet Technologies.ru - довольно молодой и (возможно :-) по-этому живой ресурс
  • DeForum.ru - Российский дизайнерский форум. Самый популярный и цитируемый дизайнерский ресурс Рунета
  • Дистанционное обучение персонала, курсы Microsoft, Sun, Veritas в учебном центре REDCENTER.

Зарубежные сайты:

Информационные ресурсы:

Программное обеспечение:


Если у вас небольшая компания и недостаточно площадей, для вас будут актуальны обеды в офис! Заказ обедов - это та самая возможность нормально поесть на работе, не тратя массу лишнего времени, нервов и денег.