// calculates the distance from start to the point projected onto the line private double getDistanceAlongLine(GpxPoint point) { double distanceA = 1000 * GpxParser.gpsToGpx(startingPoint).GetDistanceFrom(point); // distances to start point double cos_phi = getCosPhi(point); return(cos_phi * distanceA); }
public void Constructor_Coordinate_CreatesPointWithPositionAndNullTimestamp() { var target = new GpxPoint(_coordinate); Assert.Equal(_coordinate, target.Position); Assert.Null(target.Timestamp); }
private GpxPoint ReadGarminAutoRoutePoint() { GpxPoint point = new GpxPoint(); string elementName = reader.Name; bool isEmptyElement = reader.IsEmptyElement; GetPointLocation(point); if (isEmptyElement) { return(point); } while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: reader.SkipElement(); break; case XmlNodeType.EndElement: if (reader.Name != elementName) { throw new FormatException(reader.Name); } return(point); } } throw new FormatException(elementName); }
/// <summary> /// Reads a GPX traxk segment from the intrnal XmlReader. /// </summary> /// <returns>the track parsed from the XmlReader</returns> private GpxTrackSegment ReadTrackSegment() { GpxTrackSegment result = new GpxTrackSegment(); if (_xmlReader.IsEmptyElement == false) { _xmlReader.Read(); while ((_xmlReader.NodeType == XmlNodeType.EndElement && _xmlReader.Name == "trkseg") == false) { if (_xmlReader.Name == "trkpt") { GpxPoint point = ReadPoint("trkpt"); result.Points.Add(point); } else { _xmlReader.Skip(); } } } _xmlReader.Skip(); return(result); }
public static void AssertPoint(this GpxPoint point, decimal expectedLatitude, decimal expectedLongitude, decimal expectedElevation, string expectedTime) { Assert.That(point.Latitude, Is.EqualTo(expectedLatitude)); Assert.That(point.Longitude, Is.EqualTo(expectedLongitude)); Assert.That(point.Elevation, Is.EqualTo(expectedElevation)); Assert.That(point.Time, Is.EqualTo(DateTime.Parse(expectedTime, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal))); }
private static Waypoint ConvertWaypoint(GpxPoint wptType) { var point = wptType.eleSpecified ? new Point((double)wptType.lat, (double)wptType.lon, (double)wptType.ele) : new Point((double)wptType.lat, (double)wptType.lon); var time = wptType.timeSpecified ? wptType.time : (DateTime?)null; return(new Waypoint(point, time, wptType.name, wptType.cmt, wptType.desc)); }
/// <summary> /// Creates a GpxPoint with the same Longitude and Latitude as a GpsLocation. /// </summary> /// <param name="gpsLocation">the GpsLocation</param> /// <returns>the corrresponding GpxPoint</returns> public static GpxPoint gpsToGpx(GpsLocation gpsLocation) { GpxPoint point = new GpxPoint(); point.Longitude = gpsLocation.Longitude; point.Latitude = gpsLocation.Latitude; return(point); }
public static double GetSpeed(GpxPoint point1, GpxPoint point2) { if (point1.Time == null || point2.Time == null) { throw new Exception("其中一个点的时间为空"); } return(GetSpeed(point1, point2, TimeSpan.FromMilliseconds(Math.Abs((point1.Time - point2.Time).TotalMilliseconds)))); }
public void Constructor_LonLatElevationTimestamp_CreatesPointWithPositionAndTimestamp() { var timestamp = DateTime.Now; var target = new GpxPoint(_xOrdinate, _yOrdinate, _zOrdinate, timestamp); Assert.Equal(_coordinate, target.Position); Assert.Equal(timestamp, target.Timestamp); }
private void WriteSubPoint(GpxPoint point) { Writer_.WriteStartElement("rpt", GpxNamespaces.GARMIN_EXTENSIONS_NAMESPACE); Writer_.WriteAttributeString("lat", point.Latitude.ToString(CultureInfo.InvariantCulture)); Writer_.WriteAttributeString("lon", point.Longitude.ToString(CultureInfo.InvariantCulture)); Writer_.WriteEndElement(); }
private void GetPointLocation(GpxPoint point) { while (reader.MoveToNextAttribute()) { switch (reader.Name) { case GpxSymbol.Latitude: point.Latitude = Angle.FromDegrees(double.Parse(reader.Value, CultureInfo.InvariantCulture.NumberFormat)); break; case GpxSymbol.Longitude: point.Longitude = Angle.FromDegrees(double.Parse(reader.Value, CultureInfo.InvariantCulture.NumberFormat)); break; } } }
internal static IEnumerable <GpxPoint> ToGpxPoints <T>(this IEnumerable <T> points) where T : GpxPoint { foreach (T gpxPoint in points) { GpxPoint point = new GpxPoint { Longitude = gpxPoint.Longitude, Latitude = gpxPoint.Latitude, Elevation = gpxPoint.Elevation, Time = gpxPoint.Time }; yield return(point); } }
private void GetPointLocation(GpxPoint point) { while (Reader_.MoveToNextAttribute()) { switch (Reader_.Name) { case "lat": point.Latitude = double.Parse(Reader_.Value, CultureInfo.InvariantCulture.NumberFormat); break; case "lon": point.Longitude = double.Parse(Reader_.Value, CultureInfo.InvariantCulture.NumberFormat); break; } } }
public void Read_ParsesMultipleWaypoints() { var data = TestDataReader.Open("gpx-waypoint-multiple.gpx"); GpxReader target = new GpxReader(data, new GpxReaderSettings() { ReadMetadata = false }); GpxPoint result = null; int count = 0; while ((result = target.Read() as GpxPoint) != null) { count++; } Assert.Equal(3, count); }
public void Read_ParsesMultipleWaypoints() { MemoryStream data = new MemoryStream(GpxTestData.gpx_waypoint_multiple); GpxReader target = new GpxReader(data, new GpxReaderSettings() { ReadMetadata = false }); GpxPoint result = null; int count = 0; while ((result = target.Read() as GpxPoint) != null) { count++; } Assert.Equal(3, count); }
/// <summary> /// 获取一组点经过滤波后的速度 /// </summary> /// <param name="points">点的集合</param> /// <param name="sampleCount">每一组采样点的个数</param> /// <param name="jump">每一次循环跳跃的个数。比如设置5,采样10,那么第一轮1-10,第二轮6-15</param> /// <returns></returns> public static IEnumerable <SpeedInfo> GetMeanFilteredSpeeds(GpxPointCollection points, int sampleCount, int jump, double min = double.MinValue, double max = double.MaxValue) { var sortedPoints = points.TimeOrderedPoints; if (sampleCount > sortedPoints.Count) { return(new SpeedInfo[] { new SpeedInfo(sortedPoints) }); } GpxPoint last = null; List <double> distances = new List <double>(); foreach (var point in points) { if (last != null) { distances.Add(Calculate.Distance(last, point)); } last = point; } List <SpeedInfo> speedList = new List <SpeedInfo>(); for (int i = sampleCount - 1; i < sortedPoints.Count; i += jump) { DateTime minTime = sortedPoints[i - sampleCount + 1].Time; DateTime maxTime = sortedPoints[i].Time; double totalDistance = 0; for (int j = i - sampleCount + 1; j < i; j++) { totalDistance += distances[j]; } double speed = totalDistance / (maxTime - minTime).TotalSeconds; if (speed < min) { continue; } if (speed > max) { continue; } speedList.Add(new SpeedInfo(minTime, maxTime, speed)); } return(speedList); }
public void Save_IGpxWriter_WritesDataToWriter() { var waypoint = new GpxPoint(); var route = new GpxRoute(); var track = new GpxTrack(); Mock <IGpxWriter> writerM = new Mock <IGpxWriter>(); writerM.Setup(w => w.Write(waypoint)).Verifiable(); writerM.Setup(w => w.Write(route)).Verifiable(); writerM.Setup(w => w.Write(track)).Verifiable(); var target = new GpxDocument(new[] { waypoint }, new[] { route }, new[] { track }); target.Save(writerM.Object); writerM.Verify(w => w.Write(waypoint), Times.Once()); writerM.Verify(w => w.Write(route), Times.Once()); writerM.Verify(w => w.Write(track), Times.Once()); }
public static double GetSpeed(IEnumerable <GpxPoint> points) { if (points.Any(p => p.Time == null)) { throw new Exception("其中一个点的时间为空"); } var sortedPoints = points.OrderBy(p => p.Time); TimeSpan totalTime = sortedPoints.Last().Time - sortedPoints.First().Time; double totalDistance = 0; GpxPoint last = null; foreach (var point in sortedPoints) { if (last != null) { totalDistance += Calculate.Distance(last, point); } last = point; } return(totalDistance / totalTime.TotalSeconds); }
private GpxPoint FindNearestTrackPoint(DateTime localDateTime) { try { DateTime utcDateTime = localDateTime.ToUniversalTime(); GpxPoint closestGpx = gpxPoints.OrderBy(x => Math.Abs((x.Time - utcDateTime).Value.TotalSeconds)).FirstOrDefault(); if (Math.Abs((closestGpx.Time - utcDateTime).Value.TotalSeconds) > (int)Properties.Settings.Default.ErrorMargin) { return(null); } else { return(closestGpx); } } catch (Exception) { return(null); } }
// calculates cos(phi) where phi is the angle between the line and a line from the start point to the current point private double getCosPhi(GpxPoint point) { // distances to start/end point double distanceA = 1000 * GpxParser.gpsToGpx(startingPoint).GetDistanceFrom(point); double distanceB = 1000 * GpxParser.gpsToGpx(endPoint).GetDistanceFrom(point); // using cosine theorem; phi is the angle between the line and a line from the start point to the current point double cos_phi = (lineLength * lineLength + distanceA * distanceA - distanceB * distanceB) / (2 * lineLength * distanceA); if (cos_phi > 1) // prevents errors due to rounding { return(1); } else if (cos_phi < -1) { return(-1); } else { return(cos_phi); } }
// calculates the deviation of a point to the line private double getDeviation(GpxPoint point) { double distanceA = 1000 * GpxParser.gpsToGpx(startingPoint).GetDistanceFrom(point); // distances to start point double cos_phi = getCosPhi(point); double sin_phi = System.Math.Sqrt(1 - cos_phi * cos_phi); // deviation is the heigth of the triangle double deviation = sin_phi * distanceA; // if point is left of the line, deviation is negativ double deltaLong = endPoint.Longitude - startingPoint.Longitude; double deltaLat = endPoint.Latitude - startingPoint.Latitude; double slope = deltaLat / deltaLong; if (slope * (point.Longitude - startingPoint.Longitude) < point.Latitude - startingPoint.Latitude) { deviation *= -1; } if (startingPoint.Longitude > endPoint.Longitude) // the direction you walk the line changes left/right { deviation *= -1; } return(deviation); }
/// <summary> /// Writes the given point to the output stream /// </summary> /// <param name="point">The point to be written</param> /// <param name="pointElementName">The name of the XML element the point is to be written to</param> private void WritePoint(GpxPoint point, string pointElementName) { _xmlWriter.WriteStartElement(pointElementName); _xmlWriter.WriteAttributeString("lat", point.Position.Y.ToString(_invariantCulture)); _xmlWriter.WriteAttributeString("lon", point.Position.X.ToString(_invariantCulture)); if (!double.IsNaN(point.Position.Z)) { _xmlWriter.WriteElementString("ele", point.Position.Z.ToString(_invariantCulture)); } if (point.Timestamp != null) { _xmlWriter.WriteElementString("time", point.Timestamp.Value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", _invariantCulture)); } if (this.Settings.WriteMetadata) { this.WritePointMetadata(point.Metadata); } _xmlWriter.WriteEndElement(); }
private double GetNegativeHeightDif(GpxPoint point) { var heightDif = 0d; if (lastLimitPointEleNeg != null) { heightDif = -(point.GetElevationDifFrom(lastLimitPointEleNeg) ?? 0); } else { lastLimitPointEleNeg = point; } if (heightDif > 0) { if (heightDif < Options.LimitElevationDif) { return(0); } else { if (lastLimitPointEleNeg != null) { DescDist += point.GetDistanceFrom(lastLimitPointEleNeg); } lastLimitPointEleNeg = point; return(heightDif); } } else { if (-heightDif > Options.LimitElevationDif) { lastLimitPointEleNeg = null; } } return(0); }
private double GetPositiveHeightDif(GpxPoint point) { var heightDif = 0d; if (lastLimitPointElePos != null) { heightDif = point.GetElevationDifFrom(lastLimitPointElePos) ?? 0; } else { lastLimitPointElePos = point; } if (heightDif > 0) { if (heightDif < Options.LimitElevationDif) { return(0); } else { if (lastLimitPointElePos != null) { AscDist += point.GetDistanceFrom(lastLimitPointElePos); } lastLimitPointElePos = point; return(heightDif); } } else { if (-heightDif > Options.LimitElevationDif) { lastLimitPointElePos = null; } } return(0); }
/// <summary> /// Writes the given waypoint to the output stream /// </summary> /// <param name="waypoint">The waypoint to write</param> public void Write(GpxPoint waypoint) { WritePoint(waypoint, "wpt"); }
private GpxPoint ReadGarminAutoRoutePoint(XmlReader reader) { GpxPoint point = new GpxPoint(); string elementName = reader.Name; bool isEmptyElement = reader.IsEmptyElement; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "lat": point.Latitude = double.Parse(reader.Value, CultureInfo.InvariantCulture.NumberFormat); break; case "lon": point.Longitude = double.Parse(reader.Value, CultureInfo.InvariantCulture.NumberFormat); break; } } if (isEmptyElement) return point; while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: SkipElement(reader); break; case XmlNodeType.EndElement: if (reader.Name != elementName) throw new FormatException(reader.Name); return point; } } throw new FormatException(elementName); }
public static void AssertSection(this GpxSection gpxSection, GpxPoint expectedStartPoint, GpxPoint expectedEndPoint) { gpxSection.AssertSection(expectedStartPoint.Latitude, expectedStartPoint.Longitude, expectedStartPoint.Elevation, expectedStartPoint.Time.ToString(CultureInfo.InvariantCulture), expectedEndPoint.Latitude, expectedEndPoint.Longitude, expectedEndPoint.Elevation, expectedEndPoint.Time.ToString(CultureInfo.InvariantCulture)); }
private void WritePoint(GpxPoint point) { Writer_.WriteAttributeString("lat", point.Latitude.ToString(CultureInfo.InvariantCulture)); Writer_.WriteAttributeString("lon", point.Longitude.ToString(CultureInfo.InvariantCulture)); if (point.Elevation != null) { Writer_.WriteElementString("ele", point.Elevation.Value.ToString(CultureInfo.InvariantCulture)); } if (point.Time != null) { Writer_.WriteElementString("time", ToGpxDateString(point.Time.Value)); } if (point.MagneticVar != null) { Writer_.WriteElementString("magvar", point.MagneticVar.Value.ToString(CultureInfo.InvariantCulture)); } if (point.GeoidHeight != null) { Writer_.WriteElementString("geoidheight", point.GeoidHeight.Value.ToString(CultureInfo.InvariantCulture)); } if (point.Name != null) { Writer_.WriteElementString("name", point.Name); } if (point.Comment != null) { Writer_.WriteElementString("cmt", point.Comment); } if (point.Description != null) { Writer_.WriteElementString("desc", point.Description); } if (point.Source != null) { Writer_.WriteElementString("src", point.Source); } foreach (GpxLink link in point.Links) { WriteLink("link", link); } if (point.Symbol != null) { Writer_.WriteElementString("sym", point.Symbol); } if (point.Type != null) { Writer_.WriteElementString("type", point.Type); } if (point.FixType != null) { Writer_.WriteElementString("fix", point.FixType); } if (point.Satelites != null) { Writer_.WriteElementString("sat", point.Satelites.Value.ToString(CultureInfo.InvariantCulture)); } if (point.Hdop != null) { Writer_.WriteElementString("hdop", point.Hdop.Value.ToString(CultureInfo.InvariantCulture)); } if (point.Vdop != null) { Writer_.WriteElementString("vdop", point.Vdop.Value.ToString(CultureInfo.InvariantCulture)); } if (point.Pdop != null) { Writer_.WriteElementString("pdop", point.Pdop.Value.ToString(CultureInfo.InvariantCulture)); } if (point.AgeOfData != null) { Writer_.WriteElementString("ageofdgpsdata", point.AgeOfData.Value.ToString(CultureInfo.InvariantCulture)); } if (point.DgpsId != null) { Writer_.WriteElementString("dgpsid", point.DgpsId.Value.ToString(CultureInfo.InvariantCulture)); } }
/// <summary> /// Reads a GPX point from the internal XmlReader /// </summary> /// <param name="pointElementName">The name of the surrounding xml element</param> /// <returns>the point parsed from the XmlReader</returns> private GpxPoint ReadPoint(string pointElementName) { string latValue = _xmlReader.GetAttribute("lat"); if (string.IsNullOrEmpty(latValue)) { throw new InvalidDataException("Requested attribute 'lat' not found."); } double lat = double.Parse(latValue, _invariantCulture); string lonValue = _xmlReader.GetAttribute("lon"); if (string.IsNullOrEmpty(lonValue)) { throw new InvalidDataException("Requested attribute 'lon' not found."); } double lon = double.Parse(lonValue, _invariantCulture); double ele = double.NaN; DateTime timestamp = new DateTime(); GpxPointMetadata metadata = null; if (this.Settings.ReadMetadata) { metadata = new GpxPointMetadata(); } if (_xmlReader.IsEmptyElement == false) { _xmlReader.Read(); while ((_xmlReader.NodeType == XmlNodeType.EndElement && _xmlReader.Name == pointElementName) == false) { bool elementParsed = false; if (_xmlReader.Name == "ele") { string eleValue = _xmlReader.ReadElementString(); ele = double.Parse(eleValue, _invariantCulture); elementParsed = true; } if (_xmlReader.Name == "time") { string timeValue = _xmlReader.ReadElementString(); timestamp = DateTime.ParseExact(timeValue, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", _invariantCulture); elementParsed = true; } if (this.Settings.ReadMetadata) { elementParsed = elementParsed || this.TryReadPointMetadata(metadata); } if (!elementParsed) { _xmlReader.Skip(); } } } _xmlReader.Skip(); GpxPoint result = new GpxPoint(lon, lat, ele, timestamp); result.Metadata = metadata; return(result); }
private bool ProcessPointField(GpxPoint point) { switch (Reader_.Name) { case "ele": point.Elevation = ReadContentAsDouble(); return true; case "time": point.Time = ReadContentAsDateTime(); return true; case "magvar": point.MagneticVar = ReadContentAsDouble(); return true; case "geoidheight": point.GeoidHeight = ReadContentAsDouble(); return true; case "name": point.Name = ReadContentAsString(); return true; case "cmt": point.Comment = ReadContentAsString(); return true; case "desc": point.Description = ReadContentAsString(); return true; case "src": point.Source = ReadContentAsString(); return true; case "link": point.Links.Add(ReadGpxLink()); return true; case "sym": point.Symbol = ReadContentAsString(); return true; case "type": point.Type = ReadContentAsString(); return true; case "fix": point.FixType = ReadContentAsString(); return true; case "sat": point.Satelites = ReadContentAsInt(); return true; case "hdop": point.Hdop = ReadContentAsDouble(); return true; case "vdop": point.Vdop = ReadContentAsDouble(); return true; case "pdop": point.Pdop = ReadContentAsDouble(); return true; case "ageofdgpsdata": point.AgeOfData = ReadContentAsDouble(); return true; case "dgpsid": point.DgpsId = ReadContentAsInt(); return true; } return false; }
private GpxPoint ReadGarminAutoRoutePoint() { GpxPoint point = new GpxPoint(); string elementName = Reader_.Name; bool isEmptyElement = Reader_.IsEmptyElement; GetPointLocation(point); if (isEmptyElement) return point; while (Reader_.Read()) { switch (Reader_.NodeType) { case XmlNodeType.Element: SkipElement(); break; case XmlNodeType.EndElement: if (Reader_.Name != elementName) throw new FormatException(Reader_.Name); return point; } } throw new FormatException(elementName); }
public void GeometryType_ReturnsWaypoint() { GpxPoint target = new GpxPoint(); Assert.Equal(GpxGeometryType.Waypoint, target.GeometryType); }
private void WritePoint(GpxPoint point) { Writer_.WriteAttributeString("lat", point.Latitude.ToString(CultureInfo.InvariantCulture)); Writer_.WriteAttributeString("lon", point.Longitude.ToString(CultureInfo.InvariantCulture)); if (point.Elevation != null) Writer_.WriteElementString("ele", point.Elevation.Value.ToString(CultureInfo.InvariantCulture)); if (point.Time != null) Writer_.WriteElementString("time", ToGpxDateString(point.Time.Value)); if (point.MagneticVar != null) Writer_.WriteElementString("magvar", point.MagneticVar.Value.ToString(CultureInfo.InvariantCulture)); if (point.GeoidHeight != null) Writer_.WriteElementString("geoidheight", point.GeoidHeight.Value.ToString(CultureInfo.InvariantCulture)); if (point.Name != null) Writer_.WriteElementString("name", point.Name); if (point.Comment != null) Writer_.WriteElementString("cmt", point.Comment); if (point.Description != null) Writer_.WriteElementString("desc", point.Description); if (point.Source != null) Writer_.WriteElementString("src", point.Source); foreach (GpxLink link in point.Links) { WriteLink("link", link); } if (point.Symbol != null) Writer_.WriteElementString("sym", point.Symbol); if (point.Type != null) Writer_.WriteElementString("type", point.Type); if (point.FixType != null) Writer_.WriteElementString("fix", point.FixType); if (point.Satelites != null) Writer_.WriteElementString("sat", point.Satelites.Value.ToString(CultureInfo.InvariantCulture)); if (point.Hdop != null) Writer_.WriteElementString("hdop", point.Hdop.Value.ToString(CultureInfo.InvariantCulture)); if (point.Vdop != null) Writer_.WriteElementString("vdop", point.Vdop.Value.ToString(CultureInfo.InvariantCulture)); if (point.Pdop != null) Writer_.WriteElementString("pdop", point.Pdop.Value.ToString(CultureInfo.InvariantCulture)); if (point.AgeOfData != null) Writer_.WriteElementString("ageofdgpsdata", point.AgeOfData.Value.ToString(CultureInfo.InvariantCulture)); if (point.DgpsId != null) Writer_.WriteElementString("dgpsid", point.DgpsId.Value.ToString(CultureInfo.InvariantCulture)); }
private bool ProcessPointField(GpxPoint point) { switch (reader.Name) { case GpxSymbol.Elevation: point.Elevation = reader.ReadElementContentAsDouble(); return(true); case GpxSymbol.Time: point.Time = reader.ReadElementContentAsDateTime(); return(true); case "magvar": point.MagneticVar = reader.ReadElementContentAsDouble(); return(true); case "geoidheight": point.GeoidHeight = reader.ReadElementContentAsDouble(); return(true); case GpxSymbol.Name: point.Name = reader.ReadElementContentAsString(); return(true); case GpxSymbol.Comment: point.Comment = reader.ReadElementContentAsString(); return(true); case "desc": point.Description = reader.ReadElementContentAsString(); return(true); case "src": point.Source = reader.ReadElementContentAsString(); return(true); case "link": point.Links.Add(ReadGpxLink()); return(true); case "sym": point.Symbol = reader.ReadElementContentAsString(); return(true); case "type": point.Type = reader.ReadElementContentAsString(); return(true); case "fix": point.FixType = reader.ReadElementContentAsString(); return(true); case "sat": point.Satelites = reader.ReadElementContentAsInt(); return(true); case "hdop": point.Hdop = reader.ReadElementContentAsDouble(); return(true); case "vdop": point.Vdop = reader.ReadElementContentAsDouble(); return(true); case "pdop": point.Pdop = reader.ReadElementContentAsDouble(); return(true); case "ageofdgpsdata": point.AgeOfData = reader.ReadElementContentAsDouble(); return(true); case "dgpsid": point.DgpsId = reader.ReadElementContentAsInt(); return(true); } return(false); }
private void WriteSubPoint(string elementName, GpxPoint point) { Writer_.WriteStartElement(elementName, GARMIN_EXTENSIONS_NAMESPACE); Writer_.WriteAttributeString("lat", point.Latitude.ToString(CultureInfo.InvariantCulture)); Writer_.WriteAttributeString("lon", point.Longitude.ToString(CultureInfo.InvariantCulture)); Writer_.WriteEndElement(); }