XML w Javie: Różnice pomiędzy wersjami
Nie podano opisu zmian |
|||
| Linia 198: | Linia 198: | ||
<source lang="java"> | <source lang="java"> | ||
Film(Element node) { | |||
if (!node.getName().equals("film")) { | if (!node.getName().equals("film")) { | ||
throw new RuntimeException("Wrong element type"); | throw new RuntimeException("Wrong element type"); | ||
Wersja z 23 sty 2012, 13:55
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"));
}