Java Probleme beim Parsen einer XML Datei

commandcraxx

Ensign
Registriert
Mai 2011
Beiträge
178
Abend Liebe CB'ler,
im Zuge meines Studiums muss ich dieses Jahr eine Hausarbeit zum Thema Java Programmierung ablegen.

Im groben sollen wir die iTunes Musik Datenbank, mit den in der Vorlesung gelernten Techniken, parsen und aufbereiten.

Soweit so gut, allerdings hält sich Apple ja nicht unbedingt an Standards und, wie ich finde, ist das XML File von iTunes die blanke Hölle zum parsen. Hier mal ein Auszug:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Major Version</key><integer>1</integer>
	<key>Minor Version</key><integer>1</integer>
	<key>Date</key><date>2012-02-13T17:18:47Z</date>
	<key>Application Version</key><string>10.5.3</string>
	<key>Features</key><integer>5</integer>
	<key>Show Content Ratings</key><true/>
	<key>Music Folder</key><string>file://localhost/C:/Users/GESCHWÄRZT/Music/iTunes/iTunes%20Media/</string>
	<key>Library Persistent ID</key><string>229EC9EFA268CF7F</string>
	<key>Tracks</key>
	<dict>
		<key>626</key>
		<dict>
			<key>Track ID</key><integer>626</integer>
			<key>Name</key><string>Kalimba</string>
			<key>Artist</key><string>Mr. Scruff</string>
			<key>Album Artist</key><string>Mr. Scruff</string>
			<key>Composer</key><string>A. Carthy and A. Kingslow</string>
			<key>Album</key><string>Ninja Tuna</string>
			<key>Genre</key><string>Electronic</string>
			<key>Kind</key><string>MPEG-Audiodatei</string>
			<key>Size</key><integer>8414449</integer>
			<key>Total Time</key><integer>348055</integer>
			<key>Track Number</key><integer>1</integer>
			<key>Year</key><integer>2008</integer>
			<key>Date Modified</key><date>2009-07-14T06:32:31Z</date>
			<key>Date Added</key><date>2012-02-13T17:13:55Z</date>
			<key>Bit Rate</key><integer>192</integer>
			<key>Sample Rate</key><integer>44100</integer>
			<key>Comments</key><string>Ninja Tune Records</string>
			<key>Artwork Count</key><integer>1</integer>
			<key>Persistent ID</key><string>89F4CDF8468D8560</string>
			<key>Track Type</key><string>File</string>
			<key>Location</key><string>file://localhost/C:/Users/Public/Music/Sample%20Music/Kalimba.mp3</string>
			<key>File Folder Count</key><integer>-1</integer>
			<key>Library Folder Count</key><integer>-1</integer>
		</dict>
	</dict>
	<key>Playlists</key>

Ich habe es schon soweit geschafft, dass ich nur die Trackinfos pro Track parsen kann. Im Grunde genau dass was ich für später brauche. Doch habe ich nun ein Problem. Es tauchen in der Ausgabe leere Nodes auf. Ein Beispiel:

Code:
run:
0: 
                        
1: Track ID
2: 626
3: 
                        
4: Name
5: Kalimba
6: 
                        
7: Artist
8: Mr. Scruff
9: 
                        
10: Album Artist
11: Mr. Scruff
12: 
                        
13: Composer
14: A. Carthy and A. Kingslow
15: 
                        
16: Album
17: Ninja Tuna
18: 
                        
19: Genre
20: Electronic
21: 
                        
22: Kind
23: MPEG-Audiodatei
24: 
                        
25: Size
26: 8414449
27: 
                        
28: Total Time
29: 348055
30: 
                        
31: Track Number
32: 1
33: 
                        
34: Year
35: 2008
36: 
                        
37: Date Modified
38: 2009-07-14T06:32:31Z
39: 
                        
40: Date Added
41: 2012-02-13T17:13:55Z
42: 
                        
43: Bit Rate
44: 192
45: 
                        
46: Sample Rate
47: 44100
48: 
                        
49: Comments
50: Ninja Tune Records
51: 
                        
52: Artwork Count
53: 1
54: 
                        
55: Persistent ID
56: 89F4CDF8468D8560
57: 
                        
58: Track Type
59: File
60: 
                        
61: Location
62: file://localhost/C:/Users/Public/Music/Sample%20Music/Kalimba.mp3
63: 
                        
64: File Folder Count
65: -1
66: 
                        
67: Library Folder Count
68: -1
69: 
                
# NEXT TRACK  #
BUILD SUCCESSFUL (total time: 2 seconds)

Ich hab echt keine Ahnung woher diese Stammen könnten. Ich bin noch recht unerfahren mit dem Umgang mit dem DOM-Parser. Drum bitte ich um eure Hilfe.

Hier ist mein Code:

Code:
private static void parseDocument(Document dom){
		
        //get the root element
		Element docEle = dom.getDocumentElement();

		//get a nodelist of elements for dict
		NodeList nl = docEle.getElementsByTagName("dict");

        if(nl != null && nl.getLength() > 0) {

	for(int i = 2 ; i < nl.getLength(); i++) {

                if(nl.item(i).getTextContent().startsWith("Name")){
                  break;
                }

                NodeList TrackInfo = nl.item(i).getChildNodes();

                 for(int x = 0; x < TrackInfo.getLength(); x++){
                  System.out.println(x+": "+TrackInfo.item(x).getTextContent());
                 }

                System.out.println("# NEXT TRACK #");

               }
       }

}
 
Zuletzt bearbeitet:
Vielleicht sehe ich es nur nicht, aber wo sind die leeren Nodes?
Die Ausgabe passt mit der XML-Datei überein.

Meinst du die Zeilen 3, 6, usw.?
 
Genau die meine ich. Laut Java sind es Nodes, die in der Liste drin sind. Aber in denen steht null Information. Ich kanns mir nicht erklären hab grad einiges probiert. Aber überhaupt keine Chance, selbst der versuch, die Einträge zu löschen vorher, damit nur noch die anderen drin sind, geht nicht.


Kann es sein, dass er den Umbruch mit parst?
 
Wenn x = 0, dann liefert TrackInfo.item(x).getTextContent() nichts.

falsch (Zeile 19):
for(int x = 0; x < TrackInfo.getLength(); x++){

richtig:
for(int x = 1; x < TrackInfo.getLength(); x++){
 
Das behebt nur das die Zeile 1 verschwindet, die Idee hatte ich auch schon. :)

Schau:
Code:
run:
1: Track ID
2: 626
3: 
                        
4: Name
5: Kalimba
6: 
                        
7: Artist
8: Mr. Scruff
9: 
                        
10: Album Artist
11: Mr. Scruff
12: 
                        
13: Composer
14: A. Carthy and A. Kingslow
15: 
                        
16: Album
17: Ninja Tuna
18: 
                        
19: Genre
20: Electronic
21: 
                        
22: Kind
23: MPEG-Audiodatei
24: 
                        
25: Size
26: 8414449
27: 
                        
28: Total Time
29: 348055
30: 
                        
31: Track Number
32: 1
33: 
                        
34: Year
35: 2008
36: 
                        
37: Date Modified
38: 2009-07-14T06:32:31Z
39: 
                        
40: Date Added
41: 2012-02-13T17:13:55Z
42: 
                        
43: Bit Rate
44: 192
45: 
                        
46: Sample Rate
47: 44100
48: 
                        
49: Comments
50: Ninja Tune Records
51: 
                        
52: Artwork Count
53: 1
54: 
                        
55: Persistent ID
56: 89F4CDF8468D8560
57: 
                        
58: Track Type
59: File
60: 
                        
61: Location
62: file://localhost/C:/Users/Public/Music/Sample%20Music/Kalimba.mp3
63: 
                        
64: File Folder Count
65: -1
66: 
                        
67: Library Folder Count
68: -1
69: 
                
# NEXT TRACK #
BUILD SUCCESSFUL (total time: 0 seconds)

Mal noch zur Erklärung die Zahlen am Anfang der Zeile, ist die Nummer des Nodes in der Liste. Sprich das X in der For Schleife.
 
Gib doch mal den Namen mit aus

System.out.println(x+": " + TrackInfo.item(x).getName() + "-" +TrackInfo.item(x).getTextContent());
 
getName() - du meinst sicher getNodeName() oder?
Code:
run:
0: #text-
                        
1: key-Track ID
2: integer-626
3: #text-
                        
4: key-Name
5: string-Kalimba
6: #text-
                        
7: key-Artist
8: string-Mr. Scruff
9: #text-
                        
10: key-Album Artist
11: string-Mr. Scruff
12: #text-
                        
13: key-Composer
14: string-A. Carthy and A. Kingslow
15: #text-
                        
16: key-Album
17: string-Ninja Tuna
18: #text-
                        
19: key-Genre
20: string-Electronic
21: #text-
                        
22: key-Kind
23: string-MPEG-Audiodatei
24: #text-
                        
25: key-Size
26: integer-8414449
27: #text-
                        
28: key-Total Time
29: integer-348055
30: #text-
                        
31: key-Track Number
32: integer-1
33: #text-
                        
34: key-Year
35: integer-2008
36: #text-
                        
37: key-Date Modified
38: date-2009-07-14T06:32:31Z
39: #text-
                        
40: key-Date Added
41: date-2012-02-13T17:13:55Z
42: #text-
                        
43: key-Bit Rate
44: integer-192
45: #text-
                        
46: key-Sample Rate
47: integer-44100
48: #text-
                        
49: key-Comments
50: string-Ninja Tune Records
51: #text-
                        
52: key-Artwork Count
53: integer-1
54: #text-
                        
55: key-Persistent ID
56: string-89F4CDF8468D8560
57: #text-
                        
58: key-Track Type
59: string-File
60: #text-
                        
61: key-Location
62: string-file://localhost/C:/Users/Public/Music/Sample%20Music/Kalimba.mp3
63: #text-
                        
64: key-File Folder Count
65: integer--1
66: #text-
                        
67: key-Library Folder Count
68: integer--1
69: #text-
                
# NEXT TRACK #
BUILD SUCCESSFUL (total time: 2 seconds)


Habs, danke!

Code:
              for(int x = 0; x < TrackInfo.getLength(); x++){

                  if(TrackInfo.item(x).getNodeName() != "#text" ){
                    System.out.println(x+": " + TrackInfo.item(x).getTextContent());
                  }
                  
              }

Danke für den Tipp mit dem getNodeName()
Ist zwar nicht die beste Lösung aber sie funktioniert ^^

Code:
run:
1: Track ID
2: 626
4: Name
5: Kalimba
7: Artist
8: Mr. Scruff
10: Album Artist
11: Mr. Scruff
13: Composer
14: A. Carthy and A. Kingslow
16: Album
17: Ninja Tuna
19: Genre
20: Electronic
22: Kind
23: MPEG-Audiodatei
25: Size
26: 8414449
28: Total Time
29: 348055
31: Track Number
32: 1
34: Year
35: 2008
37: Date Modified
38: 2009-07-14T06:32:31Z
40: Date Added
41: 2012-02-13T17:13:55Z
43: Bit Rate
44: 192
46: Sample Rate
47: 44100
49: Comments
50: Ninja Tune Records
52: Artwork Count
53: 1
55: Persistent ID
56: 89F4CDF8468D8560
58: Track Type
59: File
61: Location
62: file://localhost/C:/Users/Public/Music/Sample%20Music/Kalimba.mp3
64: File Folder Count
65: -1
67: Library Folder Count
68: -1
# NEXT TRACK #
BUILD SUCCESSFUL (total time: 0 seconds)
 
Zuletzt bearbeitet:
Blöde Frage mit was liest du das Java File aus?

Schau dir mal JAXB an, damit kann man XML Files sehr leicht parsen.
Da erstellst du Java Klassen die heißen wie die Nodes im XML File und annotierst das ganze noch korrekt schreibst einen 3 Zeiler und du hast deine Befüllten Objecte.
 
Hab es geändert, mir ist klar, dass es nicht wirklich sauber war, Strings so zu vergleichen.
Hab aber statt equals, matches benutzt. Ist das schlimm?

Code:
if(TrackInfo.item(x).getNodeName().matches("#text") == false ){
                    System.out.println(x+": " + TrackInfo.item(x).getTextContent());

                  }
 
commandcraxx schrieb:
Hab aber statt equals, matches benutzt. Ist das schlimm?

Das kommt darauf an :p Das Ergebnis ist in diesem Fall das gleiche. Es kommt allerdings anders zustande, denn #text wird eben als regulärer Ausdruck interpretiert, was zum einen Overhead bedeutet, aber je nach Wert auch andere Ergebnisse als equals liefern kann bzw. mit einem Fehler abbricht, wenn der Wert keinen gültigen regulären Ausdruck darstellt.

Lange Rede, kurzer Sinn: Wenn Du zwei Strings auf Gleichheit prüfen möchtest, nimmst Du am besten equals.

commandcraxx schrieb:
Code:
if(TrackInfo.item(x).getNodeName().matches("#text") == false ){
}

Gebräuchlich ist
Code:
if([B]![/B]"#text".equals(trackInfo.item(x).getNodeName())){
}
 
Zuletzt bearbeitet:
Zurück
Oben