XML w Javie: Różnice pomiędzy wersjami

Z BioFizInfo
Przejdź do nawigacji Przejdź do wyszukiwania
Nie podano opisu zmian
 
(Nie pokazano 1 pośredniej wersji utworzonej przez tego samego użytkownika)
Linia 272: Linia 272:


Metoda <tt>toJDOM()</tt> w klasie <tt>Gwiazda</tt> wykorzystuje metodę <tt>toJDOM()</tt> z klasy <tt>Film</tt>.
Metoda <tt>toJDOM()</tt> w klasie <tt>Gwiazda</tt> wykorzystuje metodę <tt>toJDOM()</tt> z klasy <tt>Film</tt>.


<source lang="java">
<source lang="java">
Linia 302: Linia 299:
}
}
</source>
</source>
=== Całość ===
[[Media:XML_Java.tar.gz | Kompletny program]]

Aktualna wersja z 23 sty 2012, 20:54

Ten artykuł ma przybliżyć sposób wczytywania i zapisywania plików w formacie XML z poziomu języka Java.

Istnieje kilka bibliotek i metod, które mogą do tego służyć. Najłatwiejszą i najwygodniejszą jest biblioteka JDOM.

Instalacja (w NetBeans)

Po rozpakowaniu paczki pobranej ze strony projektu JDOM (http://www.jdom.org/dist/binary/jdom-1.1.2.tar.gz) w katalogu build znajdują się pliki:

  • jdom-1.1.2.jar – biblioteka JDOM
  • jdom-1.1.2-sources.jar – źródła biblioteki
  • jdom-1.1.2-javadoc.jar – dokumentacja w formacie Javadoc

Instalacja ad-hoc

Aby jednorazowo użyć JDOM w projekcie można dodać do bibliotek plik jdom-1.1.2.jar (Kliknięcie prawym przyciskiem myszy na pozycji Libraries w drzewie projektu, a następnie opcja Add JAR/Folder)

Instalacja stała

Jeżeli zamierzamy używać JDOM w wielu projektach i/lub chcemy, aby środowisko NetBeans w ramach podpowiedzi przy wpisywaniu kodu prezentowało opisy klas i metod z dokumentacji Javadoc, można na stałe dołączyć JDOM do bibliotek zarejestrowanych w środowisku NetBeans. Służy do tego opcja Tools/Libraries>New Library.... W zakładkach Classpath, Sources, Javadoc dodajemy odpowiednio pliki jdom-1.1.2.jar, jdom-1.1.2-sources.jar, jdom-1.1.2-javadoc.jar(należy użyć przycisku Add ZIP/Folder...).

Po zarejestrowaniu biblioteki w NetBeans można dodać ją do projektu opcją Add library(po kliknięciu RMB na pocyzji Libraries w drzewie projektu.


Przykład użycia biblioteki JDOM

Problem

Przypuśćmy, że mamy klasy Gwiazda i Film służące do przechowywania informacji o gwiazdach filmowych i filmach, w których wystąpiły.

Gwiazda.java

Gwiazda może mieć wiele adresów, oraz występować w wielu filmach. W poniższych przykładach brakuje metod zapewniających kapsułkowanie prywatnych atrybutów.

public class Gwiazda {
    private String nazwisko;
    private List<String> adresy = new ArrayList<String>();
    private List<Film> filmy = new ArrayList<Film>();

    Gwiazda(String nazwisko, String adres) {
        this.nazwisko = nazwisko;
        this.adresy.add(adres);
    }

    @Override
    public String toString() {
        String res = "Nazwisko: " + this.nazwisko + "\n";

        for (String adres : this.adresy) {
            res += "Adres: " + adres + "\n";
        }

        if (this.filmy.size() > 0) {
            res += "Wystapil(a) w:\n";
            for (Film film : this.filmy) {
                res += film + "\n";
            }
        }

        return res;
    }
}

Film.java

public class Film {
    private String tytul;
    private int rok;
    private int dlugosc;

    public Film(String tytul, int rok, int dlugosc) {
        this.tytul = tytul;
        this.rok = rok;
        this.dlugosc = dlugosc;
    }

    @Override
    public String toString() {
        String res = "Tytul: " + this.tytul + "\n";
        res += "Rok: " + this.rok + "\n";
        res += "Dlugosc: " + this.dlugosc + "\n";
        return res;
    }
}

gwiazdy.xml

Chcemy móc tworzyć obiekty klas Gwiazda i Film na podstawie pliku XML o strukturze, jak w poniższym przykładzie:

<?xml version="1.0" encoding="UTF-8"?>

<gwiazdy>
    <gwiazda>
        <nazwisko>Carrie Fischer</nazwisko>
        <adres>123 Maple St.</adres>
        <filmy>
            <film>
                <tytul>Gwiezdne Wojny</tytul>
                <rok>1977</rok>
                <dlugosc>93</dlugosc>
            </film>
            <film>
                <tytul>Imperium Kontratakuje</tytul>
                <rok>1980</rok>
                <dlugosc>96</dlugosc>
            </film>
            <film>
                <tytul>Powrót Jedi</tytul>
                <rok>1983</rok>
                <dlugosc>94</dlugosc>
            </film>
        </filmy>
    </gwiazda>
    <gwiazda> 
        <nazwisko>Mark Hamill</nazwisko>
        <adres>456 Oak Rd.</adres>
        <adres>789 Pine Av.</adres>
        <filmy>
            <film>
                <tytul>Imperium Kontratakuje</tytul>
                <rok>1980</rok>
                <dlugosc>96</dlugosc>
            </film>
            <film>
                <tytul>Powrót Jedi</tytul>
                <rok>1983</rok>
                <dlugosc>94</dlugosc>
            </film>
        </filmy>
    </gwiazda>
</gwiazdy>


Wczytywanie pliku XML

Biblioteka JDOM pozwala zbudować drzewo reprezentujące znaczniki XML we wczytywanym pliku.

Obiekty klasy org.jdom.Document reprezentują dokumenty XML. Mogą one być tworzone przez instancję klasy org.jdom.input.SAXBuilder m. in. na podstawie pliku w formacie XML, na który wskazuje obiekt klasy File.

SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("src/gwiazdy.xml");
Document document = (Document) builder.build(xmlFile);

Po zbudowaniu obiektu klasy Document należy z niego odczytać potrzebne informacje. Każdemu znacznikowi XML odpowiada obiekt klasy org.jdom.Element. Obiekty tej klasy wiedzą między innymi jakie wartości atrybutów ma odpowiadający im znacznik XML i jakie znaczniki zawiera.

Aby przeanalizować zawartość dokumentu XML należy rozpocząć od najbardziej zewnętrznego znacznika, który jest nazywany korzeniem dokumentu (root element).

Element rootNode = document.getRootElement();

W rozważanym przypadku jest to znacznik <gwiazdy>. Następnie dla każdego zawartego w korzeniu znacznika <gwiazda> należy stworzyć instancję obiektu klasy Gwiazda.

List list = rootNode.getChildren("gwiazda");

for (int i = 0; i < list.size(); i++) {
    Element node = (Element) list.get(i);

    Gwiazda gw = new Gwiazda(node);
    res.add(gw);
}


Klasę Gwiazda należy uzupełnić o konstruktor z argumentem typu Element

    Gwiazda(Element node) {
        if (!node.getName().equals("gwiazda")) {
            throw new RuntimeException("Wrong element type");
        }


        this.nazwisko = node.getChildText("nazwisko");

        for (Element el : (List<Element>) node.getChildren("adres")) {
            this.adresy.add(el.getText());
        }

        Element filmy = node.getChild("filmy");

        if (filmy != null) {
            for (Element el : (List<Element>) filmy.getChildren("film")) {
                this.filmy.add(new Film(el));
            }
        }
    }


Analogiczny konstruktor jest potrzeby w klasie Film

    Film(Element node) {
        if (!node.getName().equals("film")) {
            throw new RuntimeException("Wrong element type");
        }

        this.tytul = node.getChildText("tytul");
        this.rok = Integer.valueOf(node.getChildText("rok"));
        this.dlugosc = Integer.valueOf(node.getChildText("dlugosc"));
    }


Zapisywanie pliku XML

Mając dany obiekt klasy Document można zamienić go na tekstową reprezentację w formacie XML.

Należy zacząć od stworzenia obiektu klasy org.jdom.output.XMLOutputter, który ma metody pozwalające na zapisanie dokumentu XML

    XMLOutputter xmlOutput = new XMLOutputter();

Następnie można ustawić sposób formatowania, za którego opis odpowiada klasa org.jdom.output.Format.

    xmlOutput.setFormat(Format.getPrettyFormat());

Po skonfigurowaniu XMLOutputtera można wypisać dokument (doc) zakodowany w XML.

    xmlOutput.output(doc, System.out);

Aby stworzyć obiekt klasy Document tworzy się węzeł po węźle. Na początku tworzy się korzeń.

    Element res = new Element("gwiazdy");

A następnie dodaje się węzły w nim zawarte.

    for (Gwiazda gwiazda : gwiazdy) {
        res.addContent(gwiazda.toJDOM());
    }

Metody toJDOM() w klasach Gwiazda i Film produkują fragment dokumentu związany z daną gwiazdą lub filmem. Na koniec umieszcza się korzeń w dokumencie.

    Document doc = new Document(res);

Metoda toJDOM() w klasie Film wygląda następująco:

public class Film {

    ...
    
    Element toJDOM() {
        Element res=new Element("film");
        
        res.addContent(new Element("tytul").setText(this.tytul));
        res.addContent(new Element("rok").setText(String.valueOf(this.rok)));
        res.addContent(new Element("dlugosc").setText(String.valueOf(this.dlugosc)));
        
        return res;
    }
}

Metoda toJDOM() w klasie Gwiazda wykorzystuje metodę toJDOM() z klasy Film.

public class Gwiazda {

    ...

    Element toJDOM() {
        Element res = new Element("gwiazda");

        res.addContent(new Element("nazwisko").setText(this.nazwisko));
        for (String adres : this.adresy) {
            res.addContent(new Element("adres").setText(adres));
        }

        if (this.filmy.size() > 0) {
            Element filmy = new Element("filmy");
            for (Film film : this.filmy) {
                filmy.addContent(film.toJDOM());
            }
            res.addContent(filmy);

        }

        return res;
    }
}

Całość

Kompletny program