使用c#

时间:2018-02-17 05:47:50

标签: c# xml

我目前正在尝试获取一些XML数据,并将其重新编写为我正在处理的项目的另一种格式。现在我能够得到我正在做的事情的子节点,但我似乎无法让它将子节点分开。这是我得到的XML数据。

<Race xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Checkpoints>
    <Vector3>
       <X>237.477936</X>
       <Y>936.0487</Y>
       <Z>209.590744</Z>
    </Vector3>
    <Vector3>
       <X>163.06778</X>
       <Y>922.664856</Y>
       <Z>208.251434</Z>
    </Vector3>
    <Vector3>
       <X>74.3054</X>
       <Y>1022.99408</Y>
       <Z>215.625259</Z>
    </Vector3>
    <Vector3>
       <X>20.2580948</X>
       <Y>1040.94922</Y>
       <Z>217.798935</Z>
    </Vector3>
</Checkpoints>
</Race>

不,我试图抓住每个向量的X,Y和Z,并将它们构建成如下表所示,

{X, Y, Z, 8.0}

我目前正在做这个

            XmlNodeList checkNodes = doc.SelectNodes("/Race/Checkpoints");

                foreach (XmlNode aNode in checkNodes)
                {
                    for (var w = 0; w < aNode.ChildNodes.Count; w++)
                    {
                        string checkpoint = "";

                        string xPos = aNode.ChildNodes[w].InnerText.ToString();
                        string yPos = aNode.ChildNodes[w].InnerText.ToString();
                        string zPos = aNode.ChildNodes[w].InnerText.ToString();

                        checkpoint = "{" + xPos + ", " + yPos + ", " + zPos + ", 8.0},";
                        xnTextBox.AppendText(Environment.NewLine + checkpoint);
                    }
                }

但是我无法分解单个子组件,它只会输出所有这些组件

{237.477936936.0487209.590744, 237.477936936.0487209.590744, 237.477936936.0487209.590744, 8.0},
{163.06778922.664856208.251434, 163.06778922.664856208.251434, 163.06778922.664856208.251434, 8.0},
{74.30541022.99408215.625259, 74.30541022.99408215.625259, 74.30541022.99408215.625259, 8.0},

是的,我知道yPos和zPos的输出与zPos相同,因为我无法解决如何分割子节点的问题。任何帮助都会很棒,谢谢你。

修改

我已经将下面的答案创建成了一个类并且它可以工作,但是现在我有一个我需要获得的嵌套元素,但是当我尝试添加它时,它只返回一行而不是标题。

这是班级

using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;

[XmlRoot("Race")]
public class Race
{
    [XmlElement(ElementName = "Checkpoints")]
    public Checkpoints Checkpoints { get; set; }
    [XmlElement(ElementName = "SpawnPoints")]
    public SpawnPoints SpawnPoints { get; set; }
}

[XmlRoot("Vector3")]
public class Checkpoints
{
    [XmlElement(ElementName = "Vector3")]
    public List<Vector3> Vectors { get; set; }
}

[XmlRoot("Vector3")]
public class Vector3
{
    [XmlElement(ElementName = "X")]
    public double X { get; set; }

    [XmlElement(ElementName = "Y")]
    public double Y { get; set; }

    [XmlElement(ElementName = "Z")]
    public double Z { get; set; }
}

[XmlRoot("SpawnPoints")]
public class SpawnPoints
{
    [XmlElement(ElementName = "SpawnPoint")]
    public SpawnPoint SpawnPoint { get; set; }
}

[XmlRoot("Position")]
public class SpawnPoint
{
    [XmlElement(ElementName = "Position")]
    public List<Position> Positions { get; set; }
}

[XmlRoot("Position")]
public class Position
{
    [XmlElement(ElementName = "X")]
    public double X { get; set; }

    [XmlElement(ElementName = "Y")]
    public double Y { get; set; }

    [XmlElement(ElementName = "Z")]
    public double Z { get; set; }
}

这是我想要检索的XML数据。我需要得到X,Y,Z和标题。

<Race>
<SpawnPoints>
<SpawnPoint>
  <Position>
    <X>272.181335</X>
    <Y>953.0988</Y>
    <Z>211.16713</Z>
  </Position>
  <Heading>124.781677</Heading>
</SpawnPoint>
<SpawnPoint>
  <Position>
    <X>271.212</X>
    <Y>957.0102</Y>
    <Z>211.007156</Z>
  </Position>
  <Heading>121.86322</Heading>
</SpawnPoint>
<SpawnPoint>
  <Position>
    <X>270.4751</X>
    <Y>961.3033</Y>
    <Z>210.899719</Z>
  </Position>
  <Heading>118.801186</Heading>
</SpawnPoint>
<SpawnPoint>
  <Position>
    <X>270.059875</X>
    <Y>965.9859</Y>
    <Z>210.793045</Z>
  </Position>
  <Heading>106.5283</Heading>
</SpawnPoint>
<SpawnPoint>
  <Position>
    <X>269.029266</X>
    <Y>970.9914</Y>
    <Z>210.521118</Z>
  </Position>
  <Heading>107.501411</Heading>
</SpawnPoint>
<SpawnPoint>
</Race>

3 个答案:

答案 0 :(得分:0)

您可能想要使用XmlSerializer课程 来自System.Xml.Serialization命名空间。这是一个专门用于从XML派生的数据格式中提取数据的工具。这称为serialization

它分两个主要步骤:

  1. 首先,创建一组表示数据结构的类。
  2. 您创建了XmlSerializer并使用您的数据致电XmlSerializer.Deserialize
  3. 在您的方案中,您将创建三个类。 RaceCheckpointsVector3

    using System;
    using System.Xml;
    using System.Xml.Serialization;
    
    // Represents the <Race> XML tag.
    [XmlRoot("Race")]
    class Race
    {
        // Because the <Checkpoints> tag is contained by the <Race> tag,
        // the class representation of the <Checkpoints> tag should be contained
        // by the class representation of the <Race> tag.
        [XmlElement(ElementName = "Checkpoints")]
        public Checkpoints Checkpoints { get; set; }
    }
    
    // Represents a <Checkpoints> XML tag.
    [XmlRoot("Vector3")]
    class Checkpoints 
    {
        // Same as above but for <Vector3> tags.
        [XmlElement(ElementName = "Vector3")]
        public List<Vector3> Vectors { get; set; }
    }
    
    // Represents a <Vector3> XML tag.
    [XmlRoot("Vector3")]
    class Vector3 
    {
        // The <X> element in the <Vector3> tag
        [XmlElement(ElementName = "X")]
        public double X { get; set; }
    
        // Same
        [XmlElement(ElementName = "Y")]
        public double Y { get; set; }
    
        // Same
        [XmlElement(ElementName = "Z")]
        public double Z { get; set; }
    }
    

    然后,您需要创建一个XmlSerializer并使用它将XML数据反序列化为C#Race对象。

    // Wherever you get your XML from.
    // You can also use a TextReader object,
    // which means either a StreamReader or StringReader
    // so you can use strings as well.
    using(Stream xmlFile = File.OpenRead(""))
    {
        // Create a new XmlSerializer that deserializes
        // instances of the Race class from XML.
        XmlSerializer serializer = new XmlSerializer(typeof(Race));
    
        Race race = (Race)serializer.Deserialize(xmlFile);
    
        // Tada!
        // You now have all of your data in
        // a normal C# object.
    
        foreach(Vector3 vector in race.Checkpoints.Vectors) 
        {
            Console.WriteLine("X: {0} Y: {1} Z: {2}", vector.X, vector.Y, vector.Z);
        }
    }
    

    另见:

    修改

    关键是SpawnPoints不仅包含 SpawnPoint,还有很多。因此,您需要将public SpawnPoint SpawnPoint { get; set; }更改为public List<SpawnPoint> Points { get; set; }。对于Positions类中的SpawnPoint元素,反之亦然。

答案 1 :(得分:0)

这可以用LINQ简洁地完成:

XmlNodeList vecNodes = doc.SelectNodes("/Race/Checkpoints/Vector3");
var checkpoints =
  from node in vecNodes.Cast<XmlNode>()
  let dict = node.ChildNodes.Cast<XmlNode>().ToDictionary(n => n.Name, n => n.InnerText)
  select "{" + dict["X"] + ", " + dict["Y"] + ", " + dict["Z"] + ", 8.0},";

foreach (var checkpoint in checkpoints)
  Console.WriteLine(checkpoint);

{237.477936, 936.0487, 209.590744, 8.0},
{163.06778, 922.664856, 208.251434, 8.0},
{74.3054, 1022.99408, 215.625259, 8.0},
{20.2580948, 1040.94922, 217.798935, 8.0},

答案 2 :(得分:0)

我的偏好是使用xml linq并且只有一个类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            SpawnPoint.points = doc.Descendants("SpawnPoint").Select(x => new SpawnPoint() {
                x = x.Descendants("X").Select(y => (double)y).FirstOrDefault(),
                y = x.Descendants("Y").Select(y => (double)y).FirstOrDefault(),
                z = x.Descendants("Z").Select(y => (double)y).FirstOrDefault(),
                heading = (double)x.Element("Heading")
            }).ToList();
        }
    }
    public class SpawnPoint
    {
        public static List<SpawnPoint> points = new List<SpawnPoint>();

        public double x { get; set; }
        public double y { get; set; }
        public double z { get; set; }
        public double heading { get; set; }

    }
}