从XML文档C#

时间:2018-05-17 17:24:53

标签: c# xml

我正在尝试使用我的XML文档做几件事。我必须用版本号分隔csv文件的创建。版本4具有比版本3更多的字段,因此当任一版本生成csv时,它应该能够将其发送到正确的文件夹C:\ Version 3或C:\ Version 4,具体取决于orderedfields中的字段数量部分。目前我能够加载文档并获取值,但我有问题。下面的代码只给出了节点中的一个数字。它也为我提供了值,但即使代码运行,也会抛出以下异常:

  

未处理的类型' System.NullReferenceException'发生在CsvParser.exe

     

附加信息:未将对象引用设置为对象的实例。

如何在不收到错误的情况下获取每个值,并根据?

中的字段数确定版本号
XmlDocument dipConfig = new XmlDocument();
dipConfig.Load("DipConfig.xml");

foreach (XmlNode versions in dipConfig.DocumentElement.ChildNodes) /*Dip level*/
{
    //string nodename = versions.ChildNodes[0].Attributes["version"].InnerText;
    foreach (XmlNode versionNode in versions) /*Versions level*/
    {
        string versionNumber = String.Empty;
        versionNumber = versionNode.Attributes["number"].InnerText;
        Console.WriteLine(versionNumber); //only gets version # for first version

        if (versionNode.HasChildNodes)
        {
            foreach (XmlNode childNodes in versionNode) /*OrderedFields level*/
            {
                string locationPath = String.Empty;
                locationPath = childNodes.Attributes["path"].InnerText;

                Console.WriteLine(locationPath); //gets location path but throws exception
            }
        }
    }
}

XML文件

<dip>
  <versions>
    <version number="4">
      <location path="C:\xRS\Output" />
      <numberOfFields> 26 </numberOfFields>
      <orderedfields>
        <type>string</type>
        <!--<field key="&gt;&gt;Dummy" />-->
        <type>int</type>
        <!--<field key="MTCN" />-->
        <type>string</type>
        <!--<field key="Type" />-->
        <type>string</type>
        <!--<field key="Agent Name" />-->
        <type>string</type>
        <!--<field key="Operator ID." />-->
        <type>string</type>
        <!--<field key="Address" />-->
        <type>string</type>
        <!--<field key="ID Type" />-->
        <type>string</type>
        <!--<field key="ID No." />-->
        <type>string</type>
        <!--<field key="ID Issuer" />-->
        <type>string</type>
        <!--<field key="WU Card No." />-->
        <type>string</type>
        <!--<field key="Sender" />-->
        <type>string</type>
        <!--<field key="Receiver" />-->
        <type>string</type>
        <!--<field key="Originating Country" />-->
        <type>string</type>
        <!--<field key="Destination" />-->
        <type>currency</type>
        <!--<field key="Amount Sent" />-->
        <type>string</type>
        <!--<field key="Currency Sent" />-->
        <type>currency</type>
        <!--<field key="Amount Received" />-->
        <type>string</type>
        <!--<field key="Currency Received" />-->
        <type>currency</type>
        <!--<field key="Total" />-->
        <type>string</type>
        <!--<field key="UID" />-->
        <type>string</type>
        <!--<field key="Version" />-->
        <type>string</type>
        <!--<field key="Breakdown" />-->
        <type>string</type>
        <!--<field key="SuspectedFlag" />-->
        <type>string</type>
        <!--<field key="FlagReason" />-->
        <type>string</type>
        <!--<field key="&gt;&gt;File Name" />-->
        <type>string</type>
        <!--<field key="&gt;&gt;Export Date Time" />-->
      </orderedfields>
    </version>
    <version number="3">
      <location path="C:\xRS\Output" />
      <numberOfFields> 23 </numberOfFields>
      <orderedfields>
        <type>string</type>
        <!--<field key="&gt;&gt;Dummy" />-->
        <type>string</type>
        <!--<field key="MTCN" />-->
        <type>string</type>
        <!--<field key="Type" />-->
        <type>string</type>
        <!--<field key="Agent Name" />-->
        <type>string</type>
        <!--<field key="Operator ID." />-->
        <type>string</type>
        <!--<field key="Address" />-->
        <type>string</type>
        <!--<field key="ID Type" />-->
        <type>string</type>
        <!--<field key="ID No." />-->
        <type>string</type>
        <!--<field key="ID Issuer" />-->
        <type>string</type>
        <!--<field key="WU Card No." />-->
        <type>string</type>
        <!--<field key="Sender" />-->
        <type>string</type>
        <!--<field key="Receiver" />-->
        <type>string</type>
        <!--<field key="Originating Country" />-->
        <type>string</type>
        <!--<field key="Destination" />-->
        <type>currency</type>
        <!--<field key="Amount Sent" />-->
        <type>string</type>
        <!--<field key="Currency Sent" />-->
        <type>currency</type>
        <!--<field key="Amount Received" />-->
        <type>string</type>
        <!--<field key="Currency Received" />-->
        <type>currency</type>
        <!--<field key="Total" />-->
        <type>string</type>
        <!--<field key="UID" />-->
        <type>string</type>
        <!--<field key="Version" />-->
        <type>string</type>
        <!--<field key="Breakdown" />-->
        <type>string</type>
        <!--<field key="SuspectedFlag" />-->
        <type>string</type>
        <!--<field key="FlagReason" />-->
        <type>string</type>
        <!--<field key="&gt;&gt;File Name" />-->
        <type>string</type>
        <!--<field key="&gt;&gt;Export Date Time" />-->
      </orderedfields>
    </version>
  </versions>
</dip>

2 个答案:

答案 0 :(得分:1)

它在locationPath = childNodes.Attributes["path"].InnerText;上抛出异常,因为'location'之后的下一个子节点是'numberOfFields'。 'numberOfFields'节点没有名为'path'的属性,因此返回null作为.InnerText之前的对象。

您是否考虑使用反序列化和类来表示配置?您可以使用Xml2CSharp.com之类的工具,粘贴XML示例,它将转换为C#类。然后,您可以使用对象来处理配置信息。

要处理的代码

Dip dipConfig = null;
var xmlString = File.ReadAllText(@"DipConfig.xml");

using (var stream = new StringReader(xmlString))
{
    var serializer = new XmlSerializer(typeof(Dip));
    dipConfig = (Dip)serializer.Deserialize(stream);
}

foreach (var version in dipConfig.Versions.Version)
{
    Console.WriteLine(version.Number);

    foreach (var fieldType in version.Orderedfields.Type)
    {
        Console.WriteLine(fieldType);
    }
}

反序列化类

[XmlRoot(ElementName = "location")]
public class Location
{
    [XmlAttribute(AttributeName = "path")]
    public string Path { get; set; }
}

[XmlRoot(ElementName = "orderedfields")]
public class Orderedfields
{
    [XmlElement(ElementName = "type")]
    public List<string> Type { get; set; }
}

[XmlRoot(ElementName = "version")]
public class Version
{
    [XmlElement(ElementName = "location")]
    public Location Location { get; set; }
    [XmlElement(ElementName = "numberOfFields")]
    public string NumberOfFields { get; set; }
    [XmlElement(ElementName = "orderedfields")]
    public Orderedfields Orderedfields { get; set; }
    [XmlAttribute(AttributeName = "number")]
    public string Number { get; set; }
}

[XmlRoot(ElementName = "versions")]
public class Versions
{
    [XmlElement(ElementName = "version")]
    public List<Version> Version { get; set; }
}

[XmlRoot(ElementName = "dip")]
public class Dip
{
    [XmlElement(ElementName = "versions")]
    public Versions Versions { get; set; }
}

答案 1 :(得分:0)

试试xml linq:

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

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

            var groups = doc.Descendants("version")
                .GroupBy(x => (int)x.Attribute("number"))
                .ToList();

            foreach (var group in groups)
            {
                foreach (XElement row in group)
                {
                    string location = (string)row.Element("location").Attribute("path");
                    int fields = (int)row.Element("numberOfFields");
                    string[] fieldTypes = row.Descendants("type").Select(x => (string)x).ToArray();
                    Console.WriteLine("Version : '{0}', Location : '{1}', Number Of Fields : '{2}', Columns : '{3}'", group.Key.ToString(), location, fields.ToString(), string.Join(",", fieldTypes));
                }
            }
            Console.ReadLine();


        }

    }
}