I am trying to create node & edge objects from this graphml. I had some great advice that told me to use several packages, on further research, with it being an android implementation I went for simplexml.
http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php#nested
I am starting with the nodes. I have created my node class:
@Root(name="node")
public class DeserialisedNode implements Serializable {
public DeserialisedNode() {
super();
}
@Attribute(name = "id")
private int iD;
private String venueId;
@Element(name = "name")
private String name;
@Element(name = "waypoint_type")
private String type;
@Element(name = "lat")
private double latitude;
@Element(name = "lon")
private double longitude;
@Element(name = "level_id")
private int levelId;
@Element(name = "on_starting_route")
private String onStartingRoute;
@Element(name = "on_finish_route")
private String onFinishRoute;
public DeserialisedNode(int iD, String name, String type, double latitude, double longitude, int levelId, String onStartingRoute, String onFinishRoute) {
this.iD = iD;
this.name = name;
this.type = type;
this.latitude = latitude;
this.longitude = longitude;
this.levelId = levelId;
this.onStartingRoute = onStartingRoute;
this.onFinishRoute = onFinishRoute;
}
}
In my mainActivity i added:
try {
Serializer serializer = new Persister();
AssetManager assetManager = getAssets();
InputStream inputStream = assetManager.open("routing.xml");
DeserialisedNode node = serializer.read(DeserialisedNode.class, inputStream);
System.out.println("It worked! "+node.getClass().getName());
System.out.println("It worked! "+node.getClass().getName());
}
catch (Exception e) {
e.printStackTrace();
System.out.println("error! "+e.getMessage());
}
An example of the start of the xml:
<?xml version='1.0' encoding='utf-8'?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key attr.name="weight" attr.type="double" for="edge" id="weight" />
<key attr.name="edgeid" attr.type="string" for="edge" id="edgeid" />
<key attr.name="alpha" attr.type="string" for="edge" id="alpha" />
<key attr.name="intendedpathlonlat" attr.type="string" for="edge" id="intendedpathlonlat" />
<key attr.name="levelid" attr.type="string" for="edge" id="levelid" />
<key attr.name="weight" attr.type="long" for="edge" id="weight" />
<key attr.name="type" attr.type="string" for="edge" id="type" />
<key attr.name="relatedroutes" attr.type="string" for="node" id="relatedroutes" />
<key attr.name="description" attr.type="string" for="node" id="description" />
<key attr.name="title" attr.type="string" for="node" id="title" />
<key attr.name="on_finish_route" attr.type="string" for="node" id="on_finish_route" />
<key attr.name="on_starting_route" attr.type="string" for="node" id="on_starting_route" />
<key attr.name="level_id" attr.type="string" for="node" id="level_id" />
<key attr.name="waypoint_type" attr.type="string" for="node" id="waypoint_type" />
<key attr.name="name" attr.type="string" for="node" id="name" />
<key attr.name="lon" attr.type="string" for="node" id="lon" />
<key attr.name="lat" attr.type="string" for="node" id="lat" />
<graph edgedefault="directed" id="new id here">
<node id="L08-022">
<data key="lat">30.69330963</data>
<data key="lon">-53.98752537</data>
<data key="name" />
<data key="waypoint_type">escalator</data>
<data key="level_id">1080000</data>
<data key="on_starting_route" />
<data key="on_finish_route" />
</node>
<node id="L08-023">
<data key="lat">30.69318355</data>
<data key="lon">-53.98755793</data>
<data key="name" />
<data key="waypoint_type">stairs</data>
<data key="level_id">1080000</data>
<data key="on_starting_route" />
<data key="on_finish_route" />
</node>
etc......
My Error is:
W/System.err: org.simpleframework.xml.core.AttributeException: Attribute 'schemaLocation' does not have a match in class com.app.model.maps.DeserialisedNode at line 2
I need to get the node and edge data out.
The Java SimpleXML library looks like it is primarily for serializing Java objects to XML. It does support deserialization (parsing XML to Java) - but the documentation says:
org.simpleframework.xml.stream - Provides an XML parsing layer over a set of third party libraries. The stream package provides an event based XML parsing framework that can be used with several third party libraries such as DOM, StAX and the XML pull API.
In other words, it delegates to other packages.
So, here is a StAX approach. This uses the cursor-based StAX XML Stream Reader (not the alternative StAX event reader), because as it says here in the "Comparing Cursor and Iterator APIs" section:
If you are programming for a particularly memory-constrained environment, like Java ME, you can make smaller, more efficient code with the cursor API.
Here is the approach. It just parses the input file and prints out the relevant parts. It does not attempt to do anything more than that - just to demonstrate how to access the data items you need:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.XMLEvent;
...
private final String fileNameString = "C:/tmp/files/graphml.xml";
public void read() throws XMLStreamException, FileNotFoundException {
XMLInputFactory xmlif = XMLInputFactory.newInstance();
XMLStreamReader xmlr = xmlif.createXMLStreamReader(fileNameString,
new FileInputStream(fileNameString));
while (xmlr.hasNext()) {
int eventType = xmlr.next();
if (eventType == XMLEvent.START_ELEMENT) {
if (xmlr.getLocalName().equals("node")) {
if (xmlr.getAttributeCount() == 1) { // a safety check
String nodeID = xmlr.getAttributeValue(0);
System.out.println("---");
System.out.println("Node ID: " + nodeID);
}
}
if (xmlr.getLocalName().equals("data")) {
if (xmlr.getAttributeCount() == 1) { // a safety check
String dataKey = xmlr.getAttributeValue(0);
String dataValue = xmlr.getElementText();
System.out.println("Data key: " + dataKey + " Data value: " + dataValue);
}
}
}
}
}
The key part is the XMLStreamReader
object which gives you simple access to each tag's text contents, and to its attributes as well.
According to the SimpleXML spec, it should be possible to use this from SimpleXML - but I did not try that. Or perhaps you can just use StAX without SimpleXML at all.
In my case this prints the following output:
Node ID: L08-022
Data key: lat Data value: 40.69330963
Data key: lon Data value: -73.98752537
Data key: name Data value:
Data key: waypoint_type Data value: escalator
Data key: level_id Data value: 1080000
Data key: on_starting_route Data value:
Data key: on_finish_route Data value:
---
Node ID: L08-023
Data key: lat Data value: 40.69318355
Data key: lon Data value: -73.98755793
Data key: name Data value:
Data key: waypoint_type Data value: stairs
Data key: level_id Data value: 1080000
Data key: on_starting_route Data value:
Data key: on_finish_route Data value:
---
Node ID: L08-024
Data key: lat Data value: 40.69316844
Data key: lon Data value: -73.98755873
Data key: name Data value:
Data key: waypoint_type Data value: stairs
Data key: level_id Data value: 1080000
Data key: on_starting_route Data value:
Data key: on_finish_route Data value:
The sample file I used was this:
<?xml version='1.0' encoding='utf-8'?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key attr.name="weight" attr.type="double" for="edge" id="weight" />
<key attr.name="edgeid" attr.type="string" for="edge" id="edgeid" />
<key attr.name="alpha" attr.type="string" for="edge" id="alpha" />
<key attr.name="intendedpathlonlat" attr.type="string" for="edge" id="intendedpathlonlat" />
<key attr.name="levelid" attr.type="string" for="edge" id="levelid" />
<key attr.name="weight" attr.type="long" for="edge" id="weight" />
<key attr.name="type" attr.type="string" for="edge" id="type" />
<key attr.name="relatedroutes" attr.type="string" for="node" id="relatedroutes" />
<key attr.name="description" attr.type="string" for="node" id="description" />
<key attr.name="title" attr.type="string" for="node" id="title" />
<key attr.name="on_finish_route" attr.type="string" for="node" id="on_finish_route" />
<key attr.name="on_starting_route" attr.type="string" for="node" id="on_starting_route" />
<key attr.name="level_id" attr.type="string" for="node" id="level_id" />
<key attr.name="waypoint_type" attr.type="string" for="node" id="waypoint_type" />
<key attr.name="name" attr.type="string" for="node" id="name" />
<key attr.name="lon" attr.type="string" for="node" id="lon" />
<key attr.name="lat" attr.type="string" for="node" id="lat" />
<graph edgedefault="directed" id="new id here">
<node id="L08-022">
<data key="lat">40.69330963</data>
<data key="lon">-73.98752537</data>
<data key="name" />
<data key="waypoint_type">escalator</data>
<data key="level_id">1080000</data>
<data key="on_starting_route" />
<data key="on_finish_route" />
</node>
<node id="L08-023">
<data key="lat">40.69318355</data>
<data key="lon">-73.98755793</data>
<data key="name" />
<data key="waypoint_type">stairs</data>
<data key="level_id">1080000</data>
<data key="on_starting_route" />
<data key="on_finish_route" />
</node>
<node id="L08-024">
<data key="lat">40.69316844</data>
<data key="lon">-73.98755873</data>
<data key="name" />
<data key="waypoint_type">stairs</data>
<data key="level_id">1080000</data>
<data key="on_starting_route" />
<data key="on_finish_route" />
</node>
</graph>
</graphml>