linq C#获取特定元素下的所有元素值

5fjcxozz  于 2022-12-06  发布在  C#
关注(0)|答案(2)|浏览(193)

我有一个充满Location元素的XML文件,它的所有子元素都包含需要放入列表或理想情况下放入Location类型对象的信息。
我在这里定义我的位置类:

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
        }
}

下面是一个XML文件的示例:

<?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>

现在,我希望能够在方法中输入位置名称(例如:LocName0),并将Name元素下的所有值以列表的形式返回给我(Type、Index、ZClearance、Joint1、Joint2等)。我正在处理这个问题,因为Name元素不是任何元素的父元素。它是Location的子元素,所以Name下的元素不是后代,AFAIK。
下面是我编写的一个方法,试图实现我所描述的功能:

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);
            }
        }

但是,当我将位置名称和文件路径传递给方法时,会收到一个System.Xml.XmlException: 'Data at the root level is invalid. Line 1, position 1.'

68bkxrlz

68bkxrlz1#

这不是你想的那样:

XElement.Parse(filePath)

这是试图解析filePath,就好像它实际上是XML 一样。我怀疑您打算使用XElement.Load,它从文件加载XML-或者您可能会使用XDocument.Load
这将克服 initial 问题,但您的查询仍然是坏的。您希望(我相信)类似于:

var elements = XElement.Load(filePath)
    .Elements("Location")
    .Elements("Name")
    .Where(x => x.Value == teachName)
    .SelectMany(x => x.Parent.Elements());
gopyfrb3

gopyfrb32#

请尝试以下操作:

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);

            Dictionary<string, Location> dict = location.location
               .GroupBy(x => x.Name)
               .ToDictionary(x => x.Key, y => y.FirstOrDefault());
        }
    }
    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
        }
    }
}

相关问题