Hallo liebe Community,
der Mist bringt mich langsam echt auf die Palme.
Ich hab eine XML Datei, die schaut im groben so aus:
[XML]
0.309469 -0.921392 0.450065
-0.246077 0.582705 0.060732
[/XML]
So. Diese Datei möchte ich auslesen, daher habe ich mir eine Struktur überlegt.
Ich hab JVXBean.java (die enthält einen XmlElementWrapper(name=“geometries”), GeometryBean.java, PointSetBean.java.
Eigentlich wollte ich auch in die PointSetBean ein XmlElementWrapper für “points” hinzufügen, allerdings hat das nie ganz geklappt, weil es nicht funktionierte, einen XmlElementWrapper UND ein XmlJavaTypeAdapter gleichzeitig zu benutzen… (es kamm dann immer die Fehlermeldung, es muss sich bei dem Typen um eine Collection oder ein Array handeln… meines war übrigens eine ArrayList<double[]>. Nach einigem suchen via google fand ich einen BugReport für JAXB zu diesem problem…)
Also dachte ich mir, was sollst, schreibste dir halt noch eine Klasse, PointsBean.java. Die schaut jetzt so aus:
import java.util.LinkedList;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement( name = "points" )
public class PointsBean {
private int numOfPoints;
@XmlElement( name = "p" )
@XmlJavaTypeAdapter( PointAdapter.class )
public LinkedList<double[]> pointList = new LinkedList<double[]>();
/**
* @return the numOfPoints
*/
@XmlAttribute( name = "num" )
public int getNumOfPoints() {
return numOfPoints;
}
/**
* @param numOfPoints the numOfPoints to set
*/
public void setNumOfPoints(int numOfPoints) {
this.numOfPoints = numOfPoints;
}
}```
Das ist jetzt mein letzter Testversuch, daher diese wirren Sichtbarkeiten... ich hatte davor schon alles andere Probiert aber das haut nicht hin.
Jetzt werfen wir einen Blick auf PointAdapter.java:
```package meshjoinery.geometry.beans;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class PointAdapter extends XmlAdapter<String, double[]> {
@Override
public double[] unmarshal(String v) throws Exception {
//usually split lists at whitespace characters
String[] arguments = v.split(" ");
double[] points = new double[arguments.length];
// System.out.println("-> " + v);
for ( int i = 0; i < arguments.length; i++ )
points** = Double.parseDouble( arguments** );
return points;
}
@Override
public String marshal(double[] v) throws Exception {
String str = "";
for ( int i = 0; i < v.length; i++ )
str += Double.toString(v**) + " ";
return str.substring(0, str.length()-1);
}
}```
Bis hier hin geht alles gut... nur hat meine LinkedList<double[]> nach dem einlesen die Länge 0! Es wurden also keine Arrays in die Liste geschrieben...
Wenn ich die System.out.println in PointAdapter wieder rein nehme, sehe ich auch das die Methode brav für alle <p></p> ausgeführt wird.
Wenn ich statt der LinkedList<double[]> eine LinkedList<String> nehme und den adapter weglasse, ist die Liste ebenfalls vollständig.
Wenn ich für den Adapter nicht von String->double[] sondern von String->String umformen lasse und einfach jeden Wert in <p></p> in "ROFL" änder, dann funktioniert das auch... In jedem Eintrag der LinkedList<String> steht dann ROFL, genau 14290 mal...
Aber völlig egal was ich tue... er füllt diese verdammte Liste einfach nicht mit dem Double-Array...
Ich habs mit Double[] (statt double[]) versucht. Ich hab statt LinkedList alle möglichen Listen versuchen, einschließlich List<double[]>... Nichts funktioniert.
Mir gehen langsam die Ideen aus, die ich probieren könnte...
Mir wäre es auch wesentlich lieber, wenn ich mir die PointsBean sparen könnte...
In der PointSetBean hatte ich dann sowas zu stehen
```@XmlPath("points/@num")
public int num; // Attribute von <points/>
@XmlElementWrapper(name = "points")
@XmlElement(name = "p")
@XmlJavaTypeAdapter( PointAdapter.class )
public ArrayList<double[]> points = new ArrayList<double[]>(15000);```
Aber dann kam es zur oben erwähnten Fehlermeldung...
Ich verzweifel Langsam ,ich hoffe ihr könnt mir helfen. Wenn ihr mehr Code braucht kriegt ihr denn natürlich. Ich dachte nur es müsste reichen was ich euch hier gebe. Sonst wirds schnell unübersichtlich.
Ach ja einlesen tu ich das ganze sehr simpel...
```JVXBean jvx = JAXB.unmarshal(path.toFile(), JVXBean.class); // path ist der Pfad zur XML-Datei```
Und bei den ganzen Bean-Klassen liegt noch eine jaxb.properties im package worin steht:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Das brauchte ich um @XmlPath verwenden zu können, stand irgendwo im Netz.
Vielen Dank für eure Hilfe
Liebe Grüße
Highchiller
*** Edit ***
PS: Ein anderer Ansatz der klappt, wäre übrigens dieser hier. Die PointSetBean.java schaut jetzt so aus:
```package meshjoinery.geometry.beans;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement( name = "pointSet" )
@XmlAccessorType( XmlAccessType.FIELD )
public class PointSetBean {
@XmlAttribute( name = "dim" )
private int dimension;
//@XmlPath("points/@num")
private int numberOfPoints;
@XmlElementWrapper(name = "points")
@XmlElement(name = "p")
@XmlJavaTypeAdapter( PointAdapter.class )
private ArrayList<double[]> points;
//@XmlElement( name = "points" )
//private PointsBean points;
public ArrayList<double[]> getPoints(){
if ( points == null ) points = new ArrayList<double[]>(numberOfPoints);
return points;
}
public void setPoints(ArrayList<double[]> points){
this.points = points;
}
public int getNumberOfPoints(){
return numberOfPoints;
}
public void setNumberOfPoints(int numberOfPoints){
this.numberOfPoints = numberOfPoints;
}
/**
* @return the dimension
*/
public int getDimension() {
return dimension;
}
/**
* @param dimension the dimension to set
*/
public void setDimension(int dimension) {
this.dimension = dimension;
}
}```
(hierfür musste ich die jaxb.properties Datei entfernen... damit ist es nicht mehr möglich das Attribut von points auszulesen... aber er füllt die Liste vollständig UND KORREKT mit allen Punkten als double[]).
Wenn ich hier
```@PathXml( "points/@num" )```
wieder reinnehme UND die jaxb.properties datei wieder hinzufüge. Dann kommt die Fehlermeldung:
> javax.xml.bind.DataBindingException: javax.xml.bind.JAXBException:
> Exception Description: XmlElementWrapper is only allowed on a collection or array property but [points] is not a collection or array property.
Hier die gesamter Fehlerstack, falls es hilft:
[SPOILER]javax.xml.bind.DataBindingException: javax.xml.bind.JAXBException:
Exception Description: XmlElementWrapper is only allowed on a collection or array property but [points] is not a collection or array property.
- with linked exception:
[Exception [EclipseLink-50015] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.JAXBException
Exception Description: XmlElementWrapper is only allowed on a collection or array property but [points] is not a collection or array property.]
at javax.xml.bind.JAXB.unmarshal(JAXB.java:156)
at meshjoinery.factory.JVXFactory.readJVX(JVXFactory.java:23)
at meshjoinery.components.LoaderPanel$2.actionPerformed(LoaderPanel.java:52)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:290)
at java.awt.Component.processMouseEvent(Component.java:6527)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6292)
at java.awt.Container.processEvent(Container.java:2234)
at java.awt.Component.dispatchEventImpl(Component.java:4883)
at java.awt.Container.dispatchEventImpl(Container.java:2292)
at java.awt.Component.dispatchEvent(Component.java:4705)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)
at java.awt.Container.dispatchEventImpl(Container.java:2278)
at java.awt.Window.dispatchEventImpl(Window.java:2739)
at java.awt.Component.dispatchEvent(Component.java:4705)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)
at java.awt.EventQueue.access$400(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.awt.EventQueue$3.run(EventQueue.java:691)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:719)
at java.awt.EventQueue$4.run(EventQueue.java:717)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:716)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: javax.xml.bind.JAXBException:
Exception Description: XmlElementWrapper is only allowed on a collection or array property but [points] is not a collection or array property.
- with linked exception:
[Exception [EclipseLink-50015] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.JAXBException
Exception Description: XmlElementWrapper is only allowed on a collection or array property but [points] is not a collection or array property.]
at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:1021)
at org.eclipse.persistence.jaxb.JAXBContext.<init>(JAXBContext.java:174)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:165)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:152)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:112)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:390)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at javax.xml.bind.JAXB$Cache.<init>(JAXB.java:112)
at javax.xml.bind.JAXB.getContext(JAXB.java:139)
at javax.xml.bind.JAXB.unmarshal(JAXB.java:153)
... 39 more
Caused by: Exception [EclipseLink-50015] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.JAXBException
Exception Description: XmlElementWrapper is only allowed on a collection or array property but [points] is not a collection or array property.
at org.eclipse.persistence.exceptions.JAXBException.invalidElementWrapper(JAXBException.java:187)
at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.finalizeProperties(AnnotationsProcessor.java:983)
at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.processClassesAndProperties(AnnotationsProcessor.java:282)
at org.eclipse.persistence.jaxb.compiler.Generator.<init>(Generator.java:150)
at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:1017)
... 56 more[/SPOILER]
Also irgendwas ist einfach mal kaputt -.-