Ich bekomme von einem Kollegen eine XML-Datei, die mich vor ein unerwartetes Problem stellt. Die XML-Dateien, die ich bisher verwendet hatte, hatten als Inhalt von Tags entweder nur Text, oder andere Tags. Aber keine Mischform. Also etwa so:
<dinge>
<information>huhu</information>
<zeugs>
<zeug>A</zeug>
<zeug>B</zeug>
</zeugs>
</dinge>
Nun aber sieht ein Exemplar dieser Dateien so aus:
<dinge>
<information>huhu<oha>ueberraschung!</oha></information>
</dinge>
Das wird wohl kaum den XML-Regeln widersprechen, immerhin gibt es sowas in HTML ja auch:
<p>Dies ist ein Satz mit einem <b>fettgeschriebenem</b> Wort.</p>
Ich weiß nur nicht so genau, wie ich dies nun parsen soll. Ich hab mal ein KKSB (oder wie sich das noch gleich abkürzte) geschrieben:
import java.io.Reader;
import java.io.StringReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
public class XmlProblemDemonstration {
public class XmlInfo {
private String information;
public String getInformation() {
return information;
}
void setInformation(String information) {
this.information = information;
}
@Override
public String toString() {
return "XmlInfo [information=" + information + "]";
}
}
public XmlInfo work(String input) {
XmlInfo xmlInfo = null;
try {
xmlInfo = tryToRead(input);
} catch (XMLStreamException exception) {
exception.printStackTrace();
}
return xmlInfo;
}
private XmlInfo tryToRead(String input) throws XMLStreamException {
Reader reader = new StringReader(input);
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader parser = factory.createXMLStreamReader(reader);
XmlInfo xmlInfo = new XmlInfo();
while (parser.hasNext()) {
parser.next();
switch (parser.getEventType()) {
case XMLStreamConstants.START_ELEMENT:
switch (parser.getLocalName()) {
case "information": {
String information = parser.getElementText();
//String information = parser.getText();
xmlInfo.setInformation(information);
break;
}
}
break;
}
}
return xmlInfo;
}
public static void main(String[] args) {
XmlProblemDemonstration demo = new XmlProblemDemonstration();
for (String input : new String[] {
"<dinge><information>foo</information></dinge>",
"<dinge><information>bar</information></dinge>",
"<dinge><information>baz<oha>ueberraschung!</oha></information></dinge>"
}) {
System.out.println("Eingabe: " + input);
XmlInfo info = demo.work(input);
if (null == info) {
System.out.println("Fehler in der Verarbeitung!");
}
else {
System.out.println("Ergebnis: " + info);
}
System.out.println();
}
}
}
Die Ausgabe ist:
Eingabe: <dinge><information>foo</information></dinge>
Ergebnis: XmlInfo [information=foo]
Eingabe: <dinge><information>bar</information></dinge>
Ergebnis: XmlInfo [information=bar]
Eingabe: <dinge><information>baz<oha>ueberraschung!</oha></information></dinge>
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,29]
Message: elementGetText() function expects text only elment but START_ELEMENT was encountered.
at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.getElementText(Unknown Source)
at xml.XmlProblemDemonstration.tryToRead(XmlProblemDemonstration.java:53)
at xml.XmlProblemDemonstration.work(XmlProblemDemonstration.java:33)
at xml.XmlProblemDemonstration.main(XmlProblemDemonstration.java:73)
Fehler in der Verarbeitung!
Gefunden habe ich schon: http://stackoverflow.com/questions/13218352/java-xmlstreamreader-how-to-get-element-text-when-text-contains-start-element
Aber wenn ich die auskommentierte Zeile mit getText statt der mit getElementText verwende, bekomme ich den folgenden Fehler:
Eingabe: <dinge><information>foo</information></dinge>
Exception in thread "main" java.lang.IllegalStateException: Current state START_ELEMENT is not among the statesCHARACTERS, COMMENT, CDATA, SPACE, ENTITY_REFERENCE, DTD valid for getText()
at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.getText(Unknown Source)
at xml.XmlProblemDemonstration.tryToRead(XmlProblemDemonstration.java:54)
at xml.XmlProblemDemonstration.work(XmlProblemDemonstration.java:33)
at xml.XmlProblemDemonstration.main(XmlProblemDemonstration.java:73)
Vermutlich nur ein Knoten in den Gedanken. Kann mich jemand in die richtige Richtung stupsen?
Ich könnte natürlich damit anfangen, diese Xml-Datei mit regulären Ausdrücken zu bearbeiten, aber eigentlich ist das ja der deutlich weniger elegante Weg, und wenn sich eine Parser-Lösung bietet, wäre das vorzuziehen.