JavaRush /Blog Jawa /Random-JV /Dasar XML kanggo Java Programmer. Bagean 3.2 saka 3 - DOM...
Ярослав
tingkat
Днепр

Dasar XML kanggo Java Programmer. Bagean 3.2 saka 3 - DOM

Diterbitake ing grup
<h2> Pambuka</h2> Halo kanggo kabeh sing maca artikel, bagean iki khusus kanggo DOM. Sabanjure bakal dikhususake kanggo JAXB lan, kanthi iki, siklus dhasar XML bakal rampung. Pisanan bakal ana teori sethithik, banjur mung praktik. Ayo dadi miwiti. <h2>DOM (Model Obyek Dokumen) - TEORI</h2>Panangan DOM dirancang kanthi cara maca kabeh XML bebarengan lan nyimpen, nggawe hirarki ing wangun wit sing bisa gampang dipindhah. lan ngakses unsur sing kita butuhake. Mangkono, kita bisa, diwenehi link menyang unsur ndhuwur, njaluk kabeh pranala menyang unsur njero. Kajaba iku, unsur sing ana ing njero unsur kasebut yaiku anak saka unsur iki, lan dadi wong tuwa. Sawise kita wis maca kabeh XML menyang memori, kita mung bakal lelungan liwat struktur lan nindakake tumindak kita perlu. A little bab bagean program saka DOM ing Jawa: DOM wis akeh antarmuka sing digawe kanggo njlèntrèhaké macem-macem data. Kabeh antarmuka iki diwenehi siji antarmuka umum - Node. Amarga, nyatane, jinis data sing paling umum ing DOM yaiku Node, sing bisa dadi apa wae. Saben Node nduweni cara migunani ing ngisor iki kanggo njupuk informasi:
  1. getNodeName– njaluk jeneng host.
  2. getNodeValue- entuk nilai node.
  3. getNodeType- entuk jinis simpul.
  4. getParentNode– entuk simpul ing ngendi simpul kasebut dumunung.
  5. getChildNodes– entuk kabeh simpul asale (simpul sing ana ing njero simpul tartamtu).
  6. getAttributes- entuk kabeh atribut simpul.
  7. getOwnerDocument– entuk dokumen simpul iki.
  8. getFirstChild/getLastChild– njaluk simpul asale pisanan / pungkasan.
  9. getLocalName– migunani nalika ngolah ruang jeneng kanggo entuk jeneng tanpa ater-ater.
  10. getTextContent– ngasilake kabeh teks ing unsur lan kabeh unsur ing unsur tartamtu, kalebu baris break lan spasi.
Cathetan ing cara 9: bakal tansah bali null kajaba sampeyan wis nggunakake setNamespaceAware(true) metode ing DocumentFactory kanggo micu pangolahan namespace. Saiki, rinci penting: cara umum kanggo kabeh Node, nanging ing Node kita bisa duwe unsur lan atribut. Lan ing kene ana pitakonan: apa nilai sing bisa diduweni unsur? Apa simpul asale sing bisa diduweni atribut? Lan liyane ora konsisten. Lan kabeh iku cukup prasaja: saben cara bakal bisa gumantung ing jinis Node . Cukup nganggo logika, mesthi, supaya ora bingung. Contone: atribut apa sing bisa diduweni? Apa makna liyane saka unsur kasebut? Nanging, supaya ora nyoba kabeh dhewe, ing dokumen resmi ana tabel sing migunani banget babagan cara kerja saben metode gumantung saka jinis Node: Kualitas dadi ala, mula ana link menyang dokumentasi (tabel ing ndhuwur kaca): Dokumentasi Node Sing paling penting kanggo dielingi:
  1. ONLY unsur duwe atribut.
  2. Unsur ora duwe makna.
  3. Jeneng simpul unsur padha karo jeneng tag, lan jeneng simpul atribut padha karo jeneng atribut.
<h2>DOM (Document Object Model) - PRACTICE</h2>Ing bagean praktis, kita bakal nganalisa macem-macem jinis tugas kanggo nggoleki informasi ing XML. Kita uga njupuk rong tugas saka artikel sadurunge kanggo mbandhingake penak. Ayo miwiti, lan luwih becik miwiti impor:
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.File;
import java.io.IOException;
Aku nyedhiyakake impor supaya sampeyan ora mbingungake kelas :) Tugas No. 1 - kita kudu entuk informasi babagan kabeh karyawan lan output menyang console saka file XML ing ngisor iki:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<company>
    <name>IT-Heaven</name>
    <offices>
        <office floor="1" room="1">
            <employees>
                <employee name="Maksim" job="Middle Software Developer" />
                <employee name="Ivan" job="Junior Software Developer" />
                <employee name="Franklin" job="Junior Software Developer" />
            </employees>
        </office>
        <office floor="1" room="2">
            <employees>
                <employee name="Herald" job="Middle Software Developer" />
                <employee name="Adam" job="Middle Software Developer" />
                <employee name="Leroy" job="Junior Software Developer" />
            </employees>
        </office>
    </offices>
</company>
Minangka kita bisa ndeleng, kita duwe kabeh informasi sing disimpen ing unsur karyawan. Kanggo nyimpen ing endi wae ing program kita, ayo nggawe kelas Employee:
public class Employee {
    private String name, job;

    public Employee(String name, String job) {
        this.name = name;
        this.job = job;
    }

    public String getName() {
        return name;
    }

    public String getJob() {
        return job;
    }
}
Saiki kita duwe katrangan babagan struktur kanggo nyimpen data, kita butuh koleksi sing bakal nyimpen karyawan. Kita bakal nggawe ing kode dhewe. Kita uga kudu nggawe Dokumen adhedhasar XML kita:
public class DOMExample {
    // Список для сотрудников из XML file
    private static ArrayList<Employee> employees = new ArrayList<>();

    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        // Получение фабрики, чтобы после получить билдер documentов.
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // Получor из фабрики билдер, который парсит XML, создает структуру Document в виде иерархического дерева.
        DocumentBuilder builder = factory.newDocumentBuilder();

        // Запарсor XML, создав структуру Document. Теперь у нас есть доступ ко всем elementм, Howим нам нужно.
        Document document = builder.parse(new File("resource/xml_file1.xml"));
    }
}
Sawise nampa dokumen kasebut, kita duwe daya tanpa wates kanggo kabeh struktur file XML. Kita bisa njupuk unsur apa wae, bali maneh kanggo mriksa data lan, umume, pendekatan sing luwih fleksibel tinimbang sing ana ing SAX. Ing konteks tugas iki, kita mung kudu ngekstrak kabeh unsur karyawan, banjur ngekstrak kabeh informasi babagan kasebut. Iku cukup prasaja:
public class DOMExample {
    // Список для сотрудников из XML file
    private static ArrayList<Employee> employees = new ArrayList<>();

    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        // Получение фабрики, чтобы после получить билдер documentов.
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // Получor из фабрики билдер, который парсит XML, создает структуру Document в виде иерархического дерева.
        DocumentBuilder builder = factory.newDocumentBuilder();

        // Запарсor XML, создав структуру Document. Теперь у нас есть доступ ко всем elementм, Howим нам нужно.
        Document document = builder.parse(new File("resource/xml_file1.xml"));

        // Получение списка всех элементов employee внутри корневого element (getDocumentElement возвращает ROOT элемент XML file).
        NodeList employeeElements = document.getDocumentElement().getElementsByTagName("employee");

        // Перебор всех элементов employee
        for (int i = 0; i < employeeElements.getLength(); i++) {
            Node employee = employeeElements.item(i);

            // Получение атрибутов каждого element
            NamedNodeMap attributes = employee.getAttributes();

            // Добавление сотрудника. Атрибут - тоже Node, потому нам нужно получить meaning атрибута с помощью метода getNodeValue()
            employees.add(new Employee(attributes.getNamedItem("name").getNodeValue(), attributes.getNamedItem("job").getNodeValue()));
        }

        // Вывод информации о каждом сотруднике
        for (Employee employee : employees)
            System.out.println(String.format("Информации о сотруднике: Name - %s, должность - %s.", employee.getName(), employee.getJob()));
    }
}
Katrangan babagan solusi iki bener ing solusi. Disaranake, sawise ndeleng kode kasebut, bali menyang teori lan maca maneh. Nyatane, kabeh wis jelas kanthi naluri. Waca komentar kasebut kanthi teliti lan ora ana pitakonan, lan yen ana, sampeyan bisa nulis ing komentar, aku bakal mangsuli, utawa ing link, utawa mung mbukak IDEA lan nyoba kanggo muter kode dhewe yen sampeyan durung nglakoni. Dadi sawise mbukak kode kita entuk output ing ngisor iki:
Информации о сотруднике: Name - Maksim, должность - Middle Software Developer.
Информации о сотруднике: Name - Ivan, должность - Junior Software Developer.
Информации о сотруднике: Name - Franklin, должность - Junior Software Developer.
Информации о сотруднике: Name - Herald, должность - Middle Software Developer.
Информации о сотруднике: Name - Adam, должность - Middle Software Developer.
Информации о сотруднике: Name - Leroy, должность - Junior Software Developer.
Nalika sampeyan bisa ndeleng, tugas wis kasil rampung! Ayo pindhah menyang tugas sabanjure :) Tugas No. 2 - jeneng unsur dilebokake saka konsol, sing sampeyan kudu nampilake informasi babagan kabeh unsur ing njero lan atribut saka file XML ing ngisor iki:
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <oracle>
        <connection value="jdbc:oracle:thin:@10.220.140.48:1521:test1" />
        <user value="secretOracleUsername" />
        <password value="111" />
    </oracle>

    <mysql>
        <connection value="jdbc:mysql:thin:@10.220.140.48:1521:test1" />
        <user value="secretMySQLUsername" />
        <password value="222" />
    </mysql>
</root>
Kabeh iku cukup prasaja: kita kudu njaluk unsur kanthi jeneng, kang kita count, lan banjur liwat kabeh kelenjar anak. Kanggo nindakake iki, sampeyan kudu ngulang kabeh kelenjar anak kabeh kelenjar anak sing unsur. Solusi kanggo masalah iki:
public class DOMExample {
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        // Ридер для считывания имени тега из консоли
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        // Получение фабрики, чтобы после получить билдер documentов.
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // Получor из фабрики билдер, который парсит XML, создает структуру Document в виде иерархического дерева.
        DocumentBuilder builder = factory.newDocumentBuilder();

        // Запарсor XML, создав структуру Document. Теперь у нас есть доступ ко всем elementм, Howим нам нужно.
        Document document = builder.parse(new File("resource/xml_file3.xml"));

        // Считывание имени тега для поиска его в файле
        String element = reader.readLine();

        // Получение списка элементов, однако для удобства будем рассматривать только первое совпадение в documentе.
        // Так же заметьте, что мы ищем элемент внутри documentа, а не рут element. Это сделано для того, чтобы рут элемент тоже искался.
        NodeList matchedElementsList = document.getElementsByTagName(element);

        // Даже если element нет, всегда будет возвращаться список, просто он будет пустым.
        // Потому, чтобы утверждать, что element нет в файле, достаточно проверить размер списка.
        if (matchedElementsList.getLength() == 0) {
            System.out.println("Tag " + element + " не был найден в файле.");
        } else {
            // Получение первого element.
            Node foundedElement = matchedElementsList.item(0);

            System.out.println("Элемент был найден!");

            // Если есть данные внутри, вызов метода для вывода всей информации
            if (foundedElement.hasChildNodes())
                printInfoAboutAllChildNodes(foundedElement.getChildNodes());
        }
    }

    /**
     * Рекурсивный метод, который будет выводить информацию про все узлы внутри всех узлов, которые пришли параметром, пока не будут перебраны все узлы.
     * @param list Список узлов.
     */
    private static void printInfoAboutAllChildNodes(NodeList list) {
        for (int i = 0; i < list.getLength(); i++) {
            Node node = list.item(i);

            // У элементов есть два вида узлов - другие элементы or текстовая информация. Потому нужно разбираться две ситуации отдельно.
            if (node.getNodeType() == Node.TEXT_NODE) {
                // Фильтрация информации, так How пробелы и переносы строчек нам не нужны. Это не информация.
                String textInformation = node.getNodeValue().replace("\n", "").trim();

                if(!textInformation.isEmpty())
                    System.out.println("Внутри element найден текст: " + node.getNodeValue());
            }
            // Если это не текст, а элемент, то обрабатываем его How элемент.
            else {
                System.out.println("Найден элемент: " + node.getNodeName() + ", его атрибуты:");

                // Получение атрибутов
                NamedNodeMap attributes = node.getAttributes();

                // Вывод информации про все атрибуты
                for (int k = 0; k < attributes.getLength(); k++)
                    System.out.println("Name атрибута: " + attributes.item(k).getNodeName() + ", его meaning: " + attributes.item(k).getNodeValue());
            }

            // Если у данного element еще остались узлы, то вывести всю информацию про все его узлы.
            if (node.hasChildNodes())
                printInfoAboutAllChildNodes(node.getChildNodes());
        }
    }
}
Katrangan babagan solusi kasebut ana ing komentar, nanging aku pengin nggambarake kanthi grafis pendekatan sing digunakake, nggunakake conto saka gambar saka teori kasebut. Kita bakal nganggep yen kita kudu nampilake informasi babagan tag html. Minangka sampeyan bisa ndeleng, kita kudu pindhah saka ndhuwur menyang ngisor saka ROOT wit. Kabeh garis minangka simpul. Ing solusi, kita bakal recursively pindhah saka awal unsur sing dipengini liwat kabeh kelenjar, lan yen siji saka simpul sawijining unsur, banjur kita uga iterate liwat kabeh kelenjar unsur iki. Dadi sawise mbukak kode kita entuk output ing ngisor iki kanggo unsur root:
Элемент был найден!
Найден элемент: oracle, его атрибуты:
Найден элемент: connection, его атрибуты:
Name атрибута: value, его meaning: jdbc:oracle:thin:@10.220.140.48:1521:test1
Найден элемент: user, его атрибуты:
Name атрибута: value, его meaning: secretOracleUsername
Найден элемент: password, его атрибуты:
Name атрибута: value, его meaning: 111
Найден элемент: mysql, его атрибуты:
Найден элемент: connection, его атрибуты:
Name атрибута: value, его meaning: jdbc:mysql:thin:@10.220.140.48:1521:test1
Найден элемент: user, его атрибуты:
Name атрибута: value, его meaning: secretMySQLUsername
Найден элемент: password, его атрибуты:
Name атрибута: value, его meaning: 222
Masalah wis kasil ditanggulangi! Tugas No. 3 - saka file XML ing ngisor iki, ing ngendi informasi babagan siswa, profesor lan karyawan disimpen, sampeyan kudu maca informasi kasebut lan ngasilake menyang console:
<?xml version="1.0" encoding="UTF-8"?>
<database>
    <students>
        <student name="Maksim" course="3" specialization="CE" />
        <student name="Stephan" course="1" specialization="CS" />
        <student name="Irvin" course="2" specialization="CE" />
    </students>

    <professors>
        <professor name="Herald" experience="7 years in University" discipline="Math" />
        <professor name="Adam" experience="4 years in University" discipline="Programming" />
        <professor name="Anton" experience="6 years in University" discipline="English" />
    </professors>

    <service>
        <member name="John" position="janitor" />
        <member name="Jordan" position="janitor" />
        <member name="Mike" position="janitor" />
    </service>
</database>
Tugas kasebut cukup prasaja, nanging menarik. Pisanan, kita kudu nggawe 4 kelas: karyawan, profesor lan mahasiswa, uga kelas abstrak umum Manungsa kanggo nggawa variabel jeneng saka saben kelas ing denominator umum: Abstrak kelas induk
public abstract class Human {
    private String name;

    public Human(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
mahasiswa
public class Student extends Human {
    private String course, specialization;

    public Student(String name, String course, String specialization) {
        super(name);
        this.course = course;
        this.specialization = specialization;
    }

    public String getCourse() {
        return course;
    }

    public String getSpecialization() {
        return specialization;
    }

    public String toString() {
        return "Голодный студент " + getName() + " " + course + "-го курса, обучающийся по специальности " + specialization;
    }
}
Profesor
public class Professor extends Human {
    private String experience, discipline;

    public Professor(String name, String experience, String discipline) {
        super(name);
        this.experience = experience;
        this.discipline = discipline;
    }

    public String getExperience() {
        return experience;
    }

    public String getDiscipline() {
        return discipline;
    }

    public String toString() {
        return "Профессор " + getName() + ", обладающий опытом: \"" + experience + "\", выкладает дисциплину " + discipline;
    }
}
Karyawan
public class Member extends Human {
    private String position;

    public Member(String name, String position) {
        super(name);
        this.position = position;
    }

    public String getPosition() {
        return position;
    }

    public String toString() {
        return "Сотрудник обслуживающего персонала " + getName() + ", должность: " + position;
    }
}
Saiki kelas kita wis siyap, kita mung kudu nulis kode kanggo entuk kabeh unsur siswa, profesor lan anggota, banjur entuk atribute. Kanggo panyimpenan, kita bakal nggunakake koleksi sing bakal nyimpen obyek saka kelas induk umum kanggo kabeh - Manungsa. Dadi, solusi kanggo masalah iki:
public class DOMExample {
    // Коллекция для хранения всех людей
    private static ArrayList<Human> humans = new ArrayList<>();

    // Константы для элементов
    private static final String PROFESSOR = "professor";
    private static final String MEMBER = "member";
    private static final String STUDENT = "student";

    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        // Получение фабрики, чтобы после получить билдер documentов.
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        // Получor из фабрики билдер, который парсит XML, создает структуру Document в виде иерархического дерева.
        DocumentBuilder builder = factory.newDocumentBuilder();

        // Запарсor XML, создав структуру Document. Теперь у нас есть доступ ко всем elementм, Howим нам нужно.
        Document document = builder.parse(new File("resource/xml_file3.xml"));

        // Получение информации про каждый элемент отдельно
        collectInformation(document, PROFESSOR);
        collectInformation(document, MEMBER);
        collectInformation(document, STUDENT);

        // Вывод информации
        humans.forEach(System.out::println);
    }

    /**
     * Метод ищет информацию про теги по имени element и вносит всю информацию в коллекцию humans.
     * @param document Документ, в котором будем искать элементы.
     * @param element Name element, теги которого нужно найти. Должна быть одна из констант, которые определяются выше.
     */
    private static void collectInformation(Document document, final String element) {
        // Получение всех элементов по имени тега.
        NodeList elements = document.getElementsByTagName(element);

        // Перебор всех найденных элементов
        for (int i = 0; i < elements.getLength(); i++) {
            // Получение всех атрибутов element
            NamedNodeMap attributes = elements.item(i).getAttributes();
            String name = attributes.getNamedItem("name").getNodeValue();

            // В зависимости от типа element, нам нужно собрать свою дополнительну информацию про каждый подкласс, а после добавить нужные образцы в коллекцию.
            switch (element) {
                case PROFESSOR: {
                    String experience = attributes.getNamedItem("experience").getNodeValue();
                    String discipline = attributes.getNamedItem("discipline").getNodeValue();

                    humans.add(new Professor(name, experience, discipline));
                } break;
                case STUDENT: {
                    String course = attributes.getNamedItem("course").getNodeValue();
                    String specialization = attributes.getNamedItem("specialization").getNodeValue();

                    humans.add(new Student(name, course, specialization));
                } break;
                case MEMBER: {
                    String position = attributes.getNamedItem("position").getNodeValue();

                    humans.add(new Member(name, position));
                } break;
            }
        }
    }
}
Elinga yen kita mung butuh jeneng unsur kanggo njupuk kabeh unsur kasebut saka dokumen kasebut. Iki banget nyederhanakake proses nemokake informasi sing sampeyan butuhake. Kabeh informasi babagan kode kasebut kalebu ing komentar. Ora ana sing anyar digunakake sing ora ana ing tugas sadurunge. Kode output:
Профессор Herald, обладающий опытом: "7 years in University", выкладает дисциплину Math
Профессор Adam, обладающий опытом: "4 years in University", выкладает дисциплину Programming
Профессор Anton, обладающий опытом: "6 years in University", выкладает дисциплину English
Сотрудник обслуживающего персонала John, должность: janitor
Сотрудник обслуживающего персонала Jordan, должность: janitor
Сотрудник обслуживающего персонала Mike, должность: janitor
Голодный студент Maksim 3-го курса, обучающийся по специальности CE
Голодный студент Stephan 1-го курса, обучающийся по специальности CS
Голодный студент Irvin 2-го курса, обучающийся по специальности CE
Masalah ditanggulangi! Rekomendasi nalika nggunakake DOM lan nalika nggunakake SAX Bentenipun antarane alat iki ing fungsi lan kacepetan. Yen sampeyan butuh fungsi sing luwih fleksibel lan bisa mbuwang kinerja program, mula pilihan sampeyan yaiku DOM, nanging yen tujuan utama sampeyan nyuda biaya memori, mula DOM ora dadi pilihan sing paling apik, amarga maca kabeh informasi saka file XML lan nyimpen iku. Mulane, metode maca urutan SAX luwih murah. Sedhela: yen sampeyan butuh kinerja - SAX, fungsi - DOM. <h2>Kesimpulan</h2>Saben programmer duwe alat dhewe-dhewe, lan, gumantung saka tugas, sampeyan kudu nggunakake alat tartamtu. Ing artikel babagan SAX lan DOM, tujuanku yaiku mulang sampeyan carane ngekstrak informasi saka file XML lan ngolah kanthi cara sing sampeyan butuhake. Nanging, sanajan sampeyan wis maca artikel kasebut, sampeyan ora bisa ngaku wis sinau babagan nggunakake alat kasebut. Sampeyan kudu latihan, nyoba kode saka artikel, ngerti cara kerjane, lan nyoba nulis dhewe. Sawise kabeh, sing paling penting yaiku latihan. Artikel pungkasan bakal diterbitake ing dina teka lan, ketoke, sawise mburi kompetisi, lan bakal pengabdian kanggo JAXB. JAXB minangka alat kanggo nyimpen obyek ing program sampeyan ing format XML. Iku kabeh, muga-muga artikel iki migunani, lan sukses ing program sampeyan :) Artikel sadurunge: [Kompetisi] Dasar XML kanggo Programmer Java - Part 3.1 saka 3 - SAX
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION