# Java XML Parse error: findet end-tags nicht



## _dp (13. Aug 2010)

Hi

Ich habe eine XML Datei, die ich mir per php selbst generiere. Diese möchte ich per Java Client nun herunterladen und parsen.
Eine XML Beispieldatei sieht in etwa so aus: <![CDATA[Arctic Infiltration]]>

Der Client läd sich diese Datei nun mit entsprechendem Request in einen String und soll ihn nun dem XML Parser übergeben. Das geschieht hier:

[Java]public boolean parseRequestString() {

		if (rawAnswer.charAt(0) == '0' && rawAnswer.charAt(1) == ':') {
			answerStatus = 0;
			debugLog.addElement("Answer reported a failure: "+rawAnswer.toString());
			return false;
		} else if (rawAnswer.charAt(0) == '1' && rawAnswer.charAt(1) == ':') {
			answerStatus = 0;
			debugLog.addElement("Answer contained a dummy response: "+rawAnswer.toString());
			return false;
		}

	try {
			DocumentBuilderFactory dbf =
				DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			InputSource is = new InputSource();
			is.setCharacterStream(new StringReader(rawAnswer.toString()));

			Document doc = db.parse(is);
			NodeList nodes = doc.getElementsByTagName("addonlist");

			// iterate the employees
			for (int i = 0; i < nodes.getLength(); i++) {
				Element element = (Element) nodes.item(i);

				NodeList name = element.getElementsByTagName("name");
				Element line = (Element) name.item(0);
				System.out.println("Name: " + getCharacterDataFromElement(line));

				NodeList title = element.getElementsByTagName("title");
				line = (Element) title.item(0);
				System.out.println("Title: " + getCharacterDataFromElement(line));
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return true;
	}

	public static String getCharacterDataFromElement(Element e) {
		Node child = e.getFirstChild();
		if (child instanceof CharacterData) {
			CharacterData cd = (CharacterData) child;
			return cd.getData();
		}
		return "?";
	}
[/Java]

Der Hauptteil ab dem try Block ist aus einem Tutorial kopiert, bis dahin bin ich noch nicht gekommen da die Exception vorher geworfen wird. Die Exception wird in Zeile 20 geworfen.

Der Error:


```
[Fatal Error] :1:869: The element type "description" must be terminated by the matching end-tag "</description>".
org.xml.sax.SAXParseException: The element type "description" must be terminated by the matching end-tag "</description>".
	at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
	at SwarmInterface.SwarmController.parseRequestString(SwarmController.java:196)
```

Ich sehe am End-Tag von </description> kein Problem, außer dass es der erste Tag ist, der nicht innerhalb einer Zeile geschlossen wird. Zeilenumbrüche möchte ich mir dennoch erhalten. Muss ich da noch eine Option beifügen?


----------



## Noctarius (13. Aug 2010)

Ich tippe eher auf einen Schreib- / Tippfehler. Zeig mal das XML


----------



## _dp (14. Aug 2010)

Das hier kommt genau so aus der Masterliste im Moment:

[xml]<?xml version="1.0" encoding="ISO-8859-1"?><addonlist cachetime="10" vrequired="1" addoncount="2">
	<addon>
		<dbtime>5</dbtime>
		<title><![CDATA[Arctic Infiltration]]></title>
		<categoryID>1</categoryID>
		<category><![CDATA[]]></category>
		<themeID>1</themeID>
		<theme><![CDATA[]]></theme>

		<playercount>4</playercount>
		<releasetype><![CDATA[Beta]]></releasetype>
		<version><![CDATA[1.1]]></version>
		<shortdescription><![CDATA[IAF receives a distress call from a mysterious SynTek Research Facility. IAF marines are sent to investigate.]]></shortdescription>
		<description><![CDATA[UPDATE: Version 1.1 is out! Changelog is included in the package.

Arctic Infiltration is a single map where your team of marines are sent to investigate a SynTek Research Facility after receiving a distress call from the facility.

Objectives are:
- Gain access into the facility
- Power up the generators
- Download data from the computers
- Proceed deeper into the facility

Working Minimap and Objective Pictures are included!

I would like to hear feedback on this map especially on balancing the aliens as I haven't tested the map with full team yet.

Steam Forum Thread here:
http://forums.steampowered.com/forums/showthread.php?t=1389956]]></description>
		<rating>13</rating>
		<date>123456</date>

		<size>5800000</size>
		<authorinfo>
			<authorname><![CDATA[Specur]]></authorname>
			<profileurl><![CDATA[http://swarmarmory.com/forums/memberlist.php?mode=viewprofile&u=1180]]></profileurl>
		</authorinfo>
		<special>0</special>
		<tags><tag><![CDATA[Arctic Infiltration]]></tag>
<tag><![CDATA[Arctic]]></tag>

<tag><![CDATA[Infiltration]]></tag>
<tag><![CDATA[Specur]]></tag>
<tag><![CDATA[map]]></tag>
<tag><![CDATA[snow]]></tag>
<tag><![CDATA[out]]></tag>
</tags>
		<screenshots></screenshots>
		<files></files>
	</addon>
	<addon>
		<dbtime>10</dbtime>

		<title><![CDATA[Midnight Harvest]]></title>
		<categoryID>2</categoryID>
		<category><![CDATA[]]></category>
		<themeID>2</themeID>
		<theme><![CDATA[]]></theme>
		<playercount>4</playercount>
		<releasetype><![CDATA[Alpha]]></releasetype>

		<version><![CDATA[1.6]]></version>
		<shortdescription><![CDATA[Journey to the planet Midnight, and kick ass]]></shortdescription>
		<description><![CDATA[A 4 map campaign, set on the planet Midnight Harvest, owned by the powerfull GeoTerra corp. You have been hired by them to help evacuate their personal on the Planets only Colony, Long Dawn, and stop the swarm from spreading any further by striking deathly a blow to the hive. 

The first map is a normal Point to point objective map, the second map will be a defence mission, third and fourth map will be set outside again, in a warmer enviroment

Currently in Alpha 
Map 1 - Alpha
Map 2 - Nearly alpha
Map 3 - WIP
Map 4 - WIP

Gameplay:
YouTube - Alien Swarm: Midnight Harvest: Gameplay trailer

PLaythrough:
http://www.youtube.com/watch?v=dX04jFQ7lx0]]></description>
		<rating>4</rating>
		<date>123456</date>
		<size>7170000</size>
		<authorinfo>

			<authorname><![CDATA[jarhchief]]></authorname>
			<profileurl><![CDATA[http://swarmarmory.com/forums/memberlist.php?mode=viewprofile&u=1161]]></profileurl>
		</authorinfo>
		<special>0</special>
		<tags><tag><![CDATA[Alien Swarm]]></tag>
</tags>
		<screenshots></screenshots>
		<files></files>
	</addon>

</addonlist>[/xml]

Die Exception ist wieder die gleiche, erneut an Zeile 20 mit diesem Text:


> [Fatal Error] :1:821: The element type "description" must be terminated by the matching end-tag "</description>".
> org.xml.sax.SAXParseException: The element type "description" must be terminated by the matching end-tag "</description>".
> at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
> at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)


Zum Testen habe ich jetzt aus der XML Ausgabe mal die <br />'s weggelassen. Das ist also genau der Text den ich per PHP aus der Datenbank hole.

Meines Erachtens sind die Tags doch richtig geschrieben, warum findet er seinen End-Tag nicht?


----------



## mvitz (14. Aug 2010)

Also folgendes nimmt er bei mir ohne Probleme...


```
package de.xmltest;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class XMLTest {

    public static void main(String[] args) {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            InputSource is = new InputSource(XMLTest.class.getResourceAsStream("test.xml"));

            Document doc = db.parse(is);
            NodeList nodes = doc.getElementsByTagName("addonlist");

            // iterate the employees
            for (int i = 0; i < nodes.getLength(); i++) {
                Element addonList = (Element) nodes.item(i);
                StringBuilder out = new StringBuilder("addonlist[");
                NamedNodeMap addonListAttributes = addonList.getAttributes();
                for (int j = 0; j < addonListAttributes.getLength(); j++) {
                    Node attribute = addonListAttributes.item(j);
                    out.append(attribute.getNodeName());
                    out.append("=");
                    out.append(attribute.getNodeValue());
                    if (j < addonListAttributes.getLength() - 1)
                        out.append(", ");
                }
                out.append("]");
                System.out.println(out.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```


----------



## Noctarius (14. Aug 2010)

Da das Syntax-Highlightning hier im Forum scheinbar auch Probleme mit dem XML hat würde ich tippen, dass da ein unsichtbares Steuerzeichen drin ist das stört.

edit: Unfug, war nur HTML- statt XML-Tag.

edit2: Sehe spontan auch keinen Fehler... Ne spezielle Einstellung für CDATA Zeugs mit mehreren Zeilen gibt es auch nicht. Nee spontan keine Ahnung wieso der Fehler kommt. Ist es genau das XML was du versuchst zu parsen?


----------



## _dp (14. Aug 2010)

Ja, ist es genau.
Wegen Steuerzeichen... hmmm

Also hier ist mal die url von der die Masterliste kommt (editiere ich später dann wieder raus): <edited>
Das muss eben mit dem XML Parser geparst werden, schlägt aber leider fehl. Habe mal deinen Code oben ausprobiert, scheint ja das selbe zu sein wie ich benutze.
Änderungen gibt das nicht, immernoch der selbe Fehler beim Parsen.

Könntest du mal versuchen die XML Datei aus der obigen URL damit zu parsen ob du den selben Fehler bekommst?

Sonst müsste ich irgendwie rausfinden welche Steuerzeichen da stören könnten. Jemand einen Vorschlag wie ich das am besten anstelle? :s


----------



## musiKk (14. Aug 2010)

Hilft zwar nur wenig, aber der W3C-Validator hat mit dem Dokument auch keine Probleme.


----------



## _dp (14. Aug 2010)

Ich habe noch bemerkt, dass wenn ich php-seitig die Zeilenumbrüche escape, er mir zumindest keine Exception mehr wirft. Scheinbar muss der SAX jeden Tag in einer Zeile haben um zu funktionieren, was das CDATA in meinen Augen etwas unnötig macht.
Gibt es da einen Weg drumrum? Oder muss ich das jetzt immer escapen und in Java dann wieder zu Steuerzeichen machen?


----------



## Noctarius (14. Aug 2010)

Normal muss SAX das auch nicht. Morgen kann ich das mal mit Lycia testen, aber im Prinzip muss da nichts escaped werden.


----------



## mvitz (14. Aug 2010)

Also folgendes funktioniert bei mir auch:


```
package de.xmltest;

import java.io.InputStream;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class XMLTest {

    public static void main(String[] args) throws Exception {
        URL url = new URL("DEINE URL VON OBEN!!!");
        InputStream in = url.openStream();

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        InputSource is = new InputSource(in);

        Document doc = db.parse(is);
        NodeList nodes = doc.getElementsByTagName("addonlist");

        // iterate the employees
        for (int i = 0; i < nodes.getLength(); i++) {
            Element addonList = (Element) nodes.item(i);
            StringBuilder out = new StringBuilder("addonlist[");
            NamedNodeMap addonListAttributes = addonList.getAttributes();
            for (int j = 0; j < addonListAttributes.getLength(); j++) {
                Node attribute = addonListAttributes.item(j);
                out.append(attribute.getNodeName());
                out.append("=");
                out.append(attribute.getNodeValue());
                if (j < addonListAttributes.getLength() - 1)
                    out.append(", ");
            }
            out.append("]");
            System.out.println(out.toString());

            NodeList addons = addonList.getElementsByTagName("addon");
            for (int k = 0; k < addons.getLength(); k++) {
                System.out.println("  addon nr " + k);
                Element addon = (Element) addons.item(k);
                
                NodeList descriptionList = addon.getElementsByTagName("description");
                for (int l = 0; l < descriptionList.getLength(); l++) {
                    Node description = descriptionList.item(l);
                    System.out.println("    Description:");
                    System.out.println("----------------------");
                    System.out.println(description.getTextContent());
                    System.out.println("----------------------");
                }
            }
        }
    }
}
```


----------



## _dp (15. Aug 2010)

Ja, scheinbar hab ich das Problem gefunden.
Wenn ich die URL erst in einen StringBuffer schreibe und anschließend auslesen will, scheint er damit Probleme zu haben. Mit einem direkten URL Input Stream macht er das problemlos.

Strange. Muss ich das halt alles etwas umfrickeln, aber ich denke so wird das auch funktionieren.

Vielen Dank für die Hilfe!


----------

