I have an XML file full of Location elements, with all of its child elements containing information that I need to essentially put into a list, or ideally put into a Location type object.
Here I define my location class:
public class Location
{
/* <Summary>
* Class that describes a location object in GPL. This class is
* used to get/put location objects from TCS
*/
#region Private Declarations
private string _msg;
private string _msgIn;
private string[] _msgRes;
private TcpIpComm _client { get; set; }
#endregion
public Location(TcpIpComm commObj, string locName)
{
_client = commObj;
Name = locName;
}
public Location(TcpIpComm commObj)
{
_client = commObj;
}
public Location()
{
}
public string Name { get; set; }
public int Index { get; set; }
public float Joint1 { get; set; }
public float Joint2 { get; set; }
public float Joint3 { get; set; }
public float Joint4 { get; set; }
public float Joint5 { get; set; }
public float Joint6 { get; set; }
public float Joint7 { get; set; }
public float ZClearance = 0;
public LocType Type { get; set; }
/// <summary>
/// 0 = cartesian,
/// 1 = angles
/// </summary>
public enum LocType
{
Cartesian = 0,
Angles = 1
}
}
Here is an example of what my XML files would look like:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfLocations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Location>
<Name>LocName0</Name>
<Type>Angles</Type>
<Index>0</Index>
<ZClearance>0</ZClearance>
<Joint1>0</Joint1>
<Joint2>0</Joint2>
<Joint3>0</Joint3>
<Joint4>0</Joint4>
<Joint5>0</Joint5>
<joint6>0</joint6>
<Joint6>0</Joint6>
</Location>
<Location>
<Name>LocName1</Name>
<Type>Angles</Type>
<Index>0</Index>
<ZClearance>0</ZClearance>
<Joint1>1</Joint1>
<Joint2>1</Joint2>
<Joint3>1</Joint3>
<Joint4>1</Joint4>
<Joint5>1</Joint5>
<joint6>1</joint6>
<Joint6>1</Joint6>
</Location>
<Location>
<Name>LocName2</Name>
<Type>Angles</Type>
<Index>0</Index>
<ZClearance>0</ZClearance>
<Joint1>2</Joint1>
<Joint2>2</Joint2>
<Joint3>2</Joint3>
<Joint4>2</Joint4>
<Joint5>2</Joint5>
<joint6>2</joint6>
<Joint6>2</Joint6>
</Location>
Now I want to be able to enter a Location name into a method (ex: LocName0), and have all the values underneath that Name element returned to me in a list (Type, Index, ZClearance, Joint1, Joint2, etc...). I'm struggling with this one because the Name element isn't a parent element of anything. It is the child element of Location, so the Elements underneath Name aren't descendants, AFAIK.
Here is one method I have written in an attempt to do what I have described:
public static void GetTeachPoint(string teachName, string filePath)
{
var listOfElems = XElement.Parse(filePath)
.Elements() // gets all elements under root
.Where(x => x.Name.LocalName.StartsWith(teachName))
.SelectMany(x => x.Elements())
.Select(x => x.Value)
.ToList();
foreach(string item in listOfElems){
MessageBox.Show(item);
}
}
However when I pass the location name and filepath into the method, I receive a
System.Xml.XmlException: 'Data at the root level is invalid. Line 1, position 1.'
CodePudding user response:
This doesn't do what you think it does:
XElement.Parse(filePath)
That's trying to parse filePath
as if it were actually XML. I suspect you meant to use XElement.Load
which loads XML from a file - or you could use XDocument.Load
, potentially.
That will get over the initial problem, but your query is still broken. You want (I believe) something like:
var elements = XElement.Load(filePath)
.Elements("Location")
.Elements("Name")
.Where(x => x.Value == teachName)
.SelectMany(x => x.Parent.Elements());
CodePudding user response:
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApp2
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(ArrayOfLocations));
ArrayOfLocations location = (ArrayOfLocations)serializer.Deserialize(reader);
}
}
public class ArrayOfLocations
{
[XmlElement("Location")]
public List<Location> location { get; set; }
}
public class Location
{
private string _msg;
private string _msgIn;
private string[] _msgRes;
public Location()
{
}
public string Name { get; set; }
public int Index { get; set; }
public float Joint1 { get; set; }
public float Joint2 { get; set; }
public float Joint3 { get; set; }
public float Joint4 { get; set; }
public float Joint5 { get; set; }
public float Joint6 { get; set; }
public float Joint7 { get; set; }
public float ZClearance = 0;
public LocType Type { get; set; }
/// <summary>
/// 0 = cartesian,
/// 1 = angles
/// </summary>
public enum LocType
{
Cartesian = 0,
Angles = 1
}
}
}