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

Z BioFizInfo
Przejdź do nawigacji Przejdź do wyszukiwania
Nie podano opisu zmian
Nie podano opisu zmian
Linia 27: Linia 27:
Przypuśćmy, że mamy klasy <tt>Gwiazda</tt> i <tt>Film</tt> służące do przechowywania informacji o gwiazdach filmowych i filmach, w których wystąpiły.
Przypuśćmy, że mamy klasy <tt>Gwiazda</tt> i <tt>Film</tt> 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.


<source lang="java">
<source lang="java">
Linia 58: Linia 60:
     }
     }
}
}
</source>
==== Film.java ====
<source lang="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;
    }
}
</source>
==== gwiazdy.xml ====
Chcemy móc tworzyć obiekty klas <tt>Gwiazda</tt> i <tt>Film</tt> na podstawie pliku XML o strukturze, jak w poniższym przykładzie:
<source lang="XML">
<?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>
</source>
=== Wczytywanie pliku XML ===
Biblioteka JDOM pozwala zbudować drzewo reprezentujące znaczniki XML we wczytywanym pliku.
Obiekty klasy <tt>org.jdom.Document</tt> reprezentują dokumenty XML. Mogą one być tworzone przez instancję klasy <tt>org.jdom.input.SAXBuilder</tt> m. in. na podstawie pliku w formacie XML, na który wskazuje obiekt klasy <tt>File</tt>.
<source lang="java">
SAXBuilder builder = new SAXBuilder();
File xmlFile = new File("src/gwiazdy.xml");
Document document = (Document) builder.build(xmlFile);
</source>
Po zbudowaniu obiektu klasy <tt>Document</tt> należy z niego odczytać potrzebne informacje. Każdemu znacznikowi XML odpowiada obiekt klasy <tt>org.jdom.Element</tt>. 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'').
<source lang="java">
Element rootNode = document.getRootElement();
</source>
W rozważanym przypadku jest to znacznik <tt>&lt;gwiazdy&gt;</tt>. Następnie dla każdego zawartego w korzeniu znacznika <tt>&lt;gwiazda&gt;</tt> należy stworzyć instancję obiektu klasy <tt>Gwiazda</tt>.
<source lang="java">
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);
}
</source>
<pre>  </pre>
<source lang="java">
</source>
<source lang="java">
</source>
</source>

Wersja z 23 sty 2012, 13:20

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);
}