Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 166 additions & 1 deletion src/Itinero/IO/Xml/Route.Xml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
* limitations under the License.
*/

using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using Itinero.Attributes;
using Itinero.IO.Xml;
using Itinero.LocalGeo;

Expand All @@ -37,11 +39,172 @@ XmlSchema IXmlSerializable.GetSchema()

void IXmlSerializable.ReadXml(XmlReader reader)
{

reader.MoveToContent();
bool isEmptyElement = reader.IsEmptyElement;
if (!isEmptyElement)
{
reader.ReadStartElement();

IAttributeCollection attributes = null;
while (reader.IsStartElement("property"))
{
var k = reader.GetAttribute("k");
var v = reader.GetAttribute("v");

if (attributes == null)
{
attributes = new AttributeCollection();
}
attributes.AddOrReplace(k, v);
reader.Read();
}
this.Attributes = attributes;

if (reader.IsStartElement("shape"))
{
reader.Read();
var listOfCoordinate = new List<Coordinate>();
while (reader.IsStartElement("c"))
{
var lat = reader.GetAttribute("lat");
var lon = reader.GetAttribute("lon");
if (lat != null && lon != null)
{
listOfCoordinate.Add(new Coordinate(float.Parse(lat), float.Parse(lon)));
}
reader.Read();
}
this.Shape = listOfCoordinate.ToArray();
reader.ReadEndElement();
}

if (reader.IsStartElement("metas"))
{
reader.Read();
var listOfMeta = new List<Meta>();
while (reader.IsStartElement("meta"))
{

var shape = int.Parse(reader.GetAttribute("shape"));
reader.Read();
var meta = new Meta()
{
Shape = shape
};
while (reader.IsStartElement("property"))
{
var k = reader.GetAttribute("k");
var v = reader.GetAttribute("v");

if (meta.Attributes == null)
{
meta.Attributes = new AttributeCollection();
}
meta.Attributes.AddOrReplace(k, v);
reader.Read();
}

listOfMeta.Add(meta);
if (reader.NodeType == XmlNodeType.EndElement)
{
reader.ReadEndElement();
}
}
this.ShapeMeta = listOfMeta.ToArray();
reader.ReadEndElement();
}

if (reader.IsStartElement("branches"))
{
reader.Read();
var listOfBranch = new List<Branch>();
while (reader.IsStartElement("branch"))
{

var shape = int.Parse(reader.GetAttribute("shape"));
var lat = float.Parse(reader.GetAttribute("lat"));
var lon = float.Parse(reader.GetAttribute("lon"));
reader.Read();
var branch = new Branch()
{
Shape = shape,
Coordinate = new Coordinate(lat, lon)
};
while (reader.IsStartElement("property"))
{
var k = reader.GetAttribute("k");
var v = reader.GetAttribute("v");
if (branch.Attributes == null)
{
branch.Attributes = new AttributeCollection();
}
branch.Attributes.AddOrReplace(k, v);
reader.Read();
}
listOfBranch.Add(branch);
if (reader.NodeType == XmlNodeType.EndElement)
{
reader.ReadEndElement();
}
}
this.Branches = listOfBranch.ToArray();
reader.ReadEndElement();
}

if (reader.IsStartElement("stops"))
{
reader.Read();
var listOfStop = new List<Stop>();
while (reader.IsStartElement("stop"))
{
var shape = int.Parse(reader.GetAttribute("shape"));
var lat = float.Parse(reader.GetAttribute("lat"));
var lon = float.Parse(reader.GetAttribute("lon"));
reader.Read();
var stop = new Stop()
{
Shape = shape,
Coordinate = new Coordinate(lat, lon)
};
while (reader.IsStartElement("property"))
{
var k = reader.GetAttribute("k");
var v = reader.GetAttribute("v");
if (stop.Attributes == null)
{
stop.Attributes = new AttributeCollection();
}
stop.Attributes.AddOrReplace(k, v);
reader.Read();
}

listOfStop.Add(stop);
if (reader.NodeType == XmlNodeType.EndElement)
{
reader.ReadEndElement();
}
}
this.Stops = listOfStop.ToArray();
reader.ReadEndElement();
}
reader.ReadEndElement();
}

}

void IXmlSerializable.WriteXml(XmlWriter writer)
{
if (this.Attributes != null)
{
foreach (var attribute in Attributes)
{
writer.WriteStartElement("property");
writer.WriteAttributeString("k", attribute.Key);
writer.WriteAttributeString("v", attribute.Value);
writer.WriteEndElement();
}
}

if (this.Shape != null)
{
writer.WriteStartElement("shape");
Expand Down Expand Up @@ -95,6 +258,8 @@ void IXmlSerializable.WriteXml(XmlWriter writer)

writer.WriteStartElement("branch");
writer.WriteAttributeString("shape", branch.Shape.ToInvariantString());
writer.WriteAttribute("lat", branch.Coordinate.Latitude.ToInvariantString());
writer.WriteAttribute("lon", branch.Coordinate.Longitude.ToInvariantString());

if (branch.Attributes != null)
{
Expand Down
114 changes: 112 additions & 2 deletions test/Itinero.Test/RouteTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
using Itinero.Attributes;
using System.Collections.Generic;
using Itinero.Navigation.Directions;

using System.IO;
using System.Xml.Serialization;

namespace Itinero.Test
{
/// <summary>
Expand Down Expand Up @@ -486,10 +488,118 @@ public void TestWriteXml()
};

var xml = route.ToXml();
Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?><route><shape><c lat=\"51.26782\" lon=\"4.8013525\" /><c lat=\"51.26822\" lon=\"4.8013525\" /></shape><metas><meta shape=\"0\" /><meta shape=\"1\"><property k=\"highway\" v=\"residential\" /></meta></metas><branches><branch shape=\"1\"><property k=\"highway\" v=\"residential\" /></branch></branches><stops><stop shape=\"1\" lat=\"51.26822\" lon=\"4.8013525\"><property k=\"address\" v=\"Pastorijstraat 102, 2275 Wechelderzande\" /></stop></stops></route>",
Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?><route><property k=\"distance\" v=\"100\" /><property k=\"time\" v=\"60\" /><shape><c lat=\"51.26782\" lon=\"4.8013525\" /><c lat=\"51.26822\" lon=\"4.8013525\" /></shape><metas><meta shape=\"0\" /><meta shape=\"1\"><property k=\"highway\" v=\"residential\" /></meta></metas><branches><branch shape=\"1\" lat=\"51.26822\" lon=\"4.8013525\"><property k=\"highway\" v=\"residential\" /></branch></branches><stops><stop shape=\"1\" lat=\"51.26822\" lon=\"4.8013525\"><property k=\"address\" v=\"Pastorijstraat 102, 2275 Wechelderzande\" /></stop></stops></route>",
xml);
}

/// <summary>
/// Tests reading a route as xml.
/// </summary>
[Test]
public void TestReadXml()
{
var expectedRoute = new Route()
{
Shape = new Coordinate[]
{
new Coordinate()
{
Latitude = 51.26782f,
Longitude = 4.8013525f
},
new Coordinate()
{
Latitude = 51.26822f,
Longitude = 4.8013525f
}
},
ShapeMeta = new Route.Meta[]
{
new Route.Meta()
{
Shape = 0
},
new Route.Meta()
{
Shape = 1,
Distance = 100,
Time = 60,
Attributes = new AttributeCollection(
new Attribute("highway", "residential")),
}
},
Stops = new Route.Stop[]
{
new Route.Stop()
{
Shape = 1,
Attributes = new AttributeCollection(
new Attribute("address", "Pastorijstraat 102, 2275 Wechelderzande")),
Coordinate = new Coordinate()
{
Latitude = 51.26821857585588f,
Longitude = 4.801352620124817f
}
}
},
Branches = new Route.Branch[]
{
new Route.Branch()
{
Shape = 1,
Attributes = new AttributeCollection(
new Attribute("highway", "residential")),
Coordinate = new Coordinate()
{
Latitude = 51.26821857585588f,
Longitude = 4.801352620124817f
}
}
},
Attributes = new AttributeCollection(),
TotalDistance = 100,
TotalTime = 60
};

var xml = expectedRoute.ToXml();

var serializer = new XmlSerializer(typeof(Route));
Route route;
using (TextReader reader = new StringReader(xml))
{
route = (Route)serializer.Deserialize(reader);
}

Assert.AreEqual(expectedRoute.Attributes, route.Attributes);
Assert.AreEqual(expectedRoute.TotalDistance, route.TotalDistance);
Assert.AreEqual(expectedRoute.TotalTime, route.TotalTime);
Assert.AreEqual(expectedRoute.Shape.Length, route.Shape.Length);
Assert.AreEqual(expectedRoute.Shape[0].Latitude, route.Shape[0].Latitude);
Assert.AreEqual(expectedRoute.Shape[0].Longitude, route.Shape[0].Longitude);
Assert.AreEqual(expectedRoute.Shape[1].Latitude, route.Shape[1].Latitude);
Assert.AreEqual(expectedRoute.Shape[1].Longitude, route.Shape[1].Longitude);

Assert.AreEqual(expectedRoute.ShapeMeta.Length, route.ShapeMeta.Length);
Assert.AreEqual(expectedRoute.ShapeMeta[0].Shape, route.ShapeMeta[0].Shape);
Assert.AreEqual(expectedRoute.ShapeMeta[0].Attributes, route.ShapeMeta[0].Attributes);

Assert.AreEqual(expectedRoute.ShapeMeta[1].Shape, route.ShapeMeta[1].Shape);
Assert.AreEqual(expectedRoute.ShapeMeta[1].Attributes.Count, route.ShapeMeta[1].Attributes.Count);
Assert.AreEqual(expectedRoute.ShapeMeta[1].Distance, route.ShapeMeta[1].Distance);
Assert.AreEqual(expectedRoute.ShapeMeta[1].Time, route.ShapeMeta[1].Time);
Assert.AreEqual(expectedRoute.ShapeMeta[1].Attributes, route.ShapeMeta[1].Attributes);

Assert.AreEqual(expectedRoute.Stops.Length, route.Stops.Length);
Assert.AreEqual(expectedRoute.Stops[0].Shape, route.Stops[0].Shape);
Assert.AreEqual(expectedRoute.Stops[0].Coordinate, route.Stops[0].Coordinate);
Assert.AreEqual(expectedRoute.Stops[0].Attributes, route.Stops[0].Attributes);

Assert.AreEqual(expectedRoute.Branches.Length, route.Branches.Length);
Assert.AreEqual(expectedRoute.Branches[0].Shape, route.Branches[0].Shape);
Assert.AreEqual(expectedRoute.Branches[0].Coordinate, route.Branches[0].Coordinate);
Assert.AreEqual(expectedRoute.Branches[0].Attributes, route.Branches[0].Attributes);
}

/// <summary>
/// Tests writing a route as geojson.
/// </summary>
Expand Down