Поиск по этому блогу

понедельник, 6 февраля 2012 г.

Java XML. DOM parser своими руками


Привет, %username%.

Сегодня делал простой DOM парсер на java. Навеяно этой статьей.
Материалов по теме достаточно, так что кидаю просто код.

Идея примера - рекурсивно обойти DOM дерево и вывести все его атрибуты.





Пусть у нас есть XML документ:

<?xml version="1.0" encoding="windows-1251"?>
<books>
    <book id="1">
        <title>Компьютерные сети</title>
        <autor>Олифер</autor>
    </book>
    <book id="2">
        <title>Вычислительные сети сети</title>
        <autor>Кто-то ещё</autor>
    </book>
</books>



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



package png.samples.xml.domread;


import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;

public class XmlDomReadSample {

    public static void main(String [] args) throws IOException, SAXException, ParserConfigurationException {
        DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
        f.setValidating(false);
        f.setIgnoringElementContentWhitespace(true);
        DocumentBuilder builder = f.newDocumentBuilder();
        Document doc = builder.parse(
          XmlDomReadSample.class.getResourceAsStream("dom-read-sample-xml.xml"));
        
        printDom("",doc.getFirstChild());
        
    }

    private static void printDom(String prefix, Node node) {
        
        String text = node.getNodeValue();
        if (text != null && !text.isEmpty()) {
            System.out.println(prefix + " value = \"" + text + "\"");
        }
        NamedNodeMap attributes = node.getAttributes();
        if (attributes != null) {
            for (int i = 0 ; i < attributes.getLength(); i++) {
                Node attr = attributes.item(i);
                System.out.println(prefix +
                        " attr = \"" + attr.getNodeName()  + "\"" +
                        " value = \"" + attr.getTextContent().toString() + "\" ");
            }
        }

        NodeList children = node.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            printDom(prefix + node.getNodeName() + ":", children.item(i));
        }
    }
}
Этот же код этого файла на github можно скачать здесь: https://github.com/png-tech/PngJavaSamples/blob/master/SimpleExamples/src/png/samples/xml/domread/XmlDomReadSample.java

Поясняю. printDom - та самая рекурсивная функция, которая реализует обход.
Берем файл из ресурсов, парсим его стандартными средствами Java, отдаем рекурсивной функции на вывод.

Ранее я писал статью про SAX. Обращу внимание ещё раз на то, что через DOM парсить, легче (меньше логики), но когда возникают вопросы производительности, то лучше SAX.

Кроме того, для упрощения работы советую разработчикам затачивать структуру XML документа под используемый способ анализа.
Для SAX анализа:

  1. делайте меньшую вложенность (в идеале документ должен быть линейным насколько это возможно);
  2. больше условий выносите в аттрибуты.


Для DOM  анализа:

  1. Лишняя иерархия тоже будет лишней, но и линейность будет ещё хуже. Лучше всего золотая середина: умная иерархия.




Исходный код примера, смотрим здесь:
 https://github.com/png-tech/PngJavaSamples/tree/master/SimpleExamples/src/png/samples/xml/domread



Комментариев нет:

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