改进从xml文件获取数据

时间:2011-10-14 12:50:04

标签: c# xml xpath

我有一个像这样的XML文件:

   <Document>
       <Tests Count="4">
          <Test>
             <Name>test with a</Name>
             <Type>VI test</Type>
             <Result>Pass</Result>
          </Test>
          <Test>
             <Name>test plot</Name>
             <Type>Curve test</Type>
             <Result>Fail</Result>
          </Test>
          <Test>
             <Name>test fixture</Name>
             <Type>Leakage test</Type>
             <Result>Pass</Result>
          </Test>      
          <Test>
             <Name>test fixture</Name>
             <Type>Leakage test</Type>
          </Test>             
        </Tests>
   </Document>

我创建了一个类来包含每个“Test”:

class TestGroup
{
    public string TestName { get; set; }
    public string TestType { get; set; }
    public string TestResult { get; set; }
}

由于我非常喜欢XML,目前我得到这样的数据(ztr是XmlDocument):

public List<TestGroup> GetTestGroups()
        {
            List<TestGroup> TestNode = new List<TestGroup>();

            string[] type_t = new string[GetTestsNumber()];
            string[] name_t = new string[GetTestsNumber()];
            string[] result_t = new string[GetTestsNumber()];

            //name
            string xpath = "/Document/Tests/Test";

            int i = 0;

            foreach (XmlElement Name in ztr.SelectNodes(xpath))
            {
                name_t[i] = Name.SelectSingleNode("Name").InnerText;
                i++;
            }
            ///////////

            //result
            xpath = "/Document/Tests/Test";

            i = 0;

            foreach (XmlElement Result in ztr.SelectNodes(xpath))
            {
                result_t[i] = Result.SelectSingleNode("Result").InnerText;
                i++;
            }
            /////////////////
            xpath = "/Document/Tests/Test";

            i = 0;

            foreach (XmlElement Type in ztr.SelectNodes(xpath))
            {
                type_t[i] = Type .SelectSingleNode("Type").InnerText;
                i++;
            }

            int count = type_t.GetLength(0);

            for (i = 0; i < count; i++)
            {
                LUTestGroup node = new LUTestGroup();
                node.TestName = name_t[i];
                node.TestType = type_t[i];
                node.TestResult = result_t[i];

                TestNode.Add(node);
            }

            return TestNode;
        }

显然这种方式非常危险。它在xml时间内分开单独的时间,每次都向类中添加一个属性。另外,如果您在示例xml文件中注意到。最后一个Test noet有一个Result节点,所以当我输入不同的XML文件时,我写的代码有时会崩溃。

你能帮我吗?请写一个方法来安全地让所有可用于XML文件的测试填充List,如果其中任何一个没有节点,该方法不会崩溃?并且必须重要,在ONE GO中完成工作!

由于

2 个答案:

答案 0 :(得分:4)

(正如评论中所述。)

LINQ to XML版本非常简单:

// Could use doc.Root.Element("Tests").Elements("Test") to be explicit
return doc.Descendants("Test")
          .Select(x => new LUTestGroup {
                      TestName = (string) x.Element("Name"),
                      TestType = (string) x.Element("Type"),
                      TestResult = (string) x.Element("Result")
                  })
          .ToList();

请注意,如果您为XElement引用,则stringXElement的强制转换将返回null,因此在您的“泄漏测试”情况下,您最终会得到LUTestGroup具有空TestResult属性。

答案 1 :(得分:3)

在我看来,你正在努力做到这一点。让系统为你解析xml!您可以注释类以告诉它xml的样子:

[XmlRoot("Document")]
public class TestWrapper {
    private readonly List<TestGroup> tests = new List<TestGroup>();
    [XmlArray("Tests"), XmlArrayItem("Test")]
    public List<TestGroup> Tests { get { return tests; } }
}

public class TestGroup {
    [XmlElement("Name")] public string TestName { get; set; }
    [XmlElement("Type")] public string TestType { get; set; }
    [XmlElement("Result")] public string TestResult { get; set; }
}

然后:

TestWrapper doc;
using(var reader = XmlReader.Create(source))
{
    var serializer = new XmlSerializer(typeof (TestWrapper));
    doc = (TestWrapper) serializer.Deserialize(reader);
}
// et voila; loaded! prove it:
foreach(var item in doc.Tests)
{
    Console.WriteLine("{0}: {1}, {2}",
        item.TestName, item.TestType, item.TestResult);
}

你也可以使用XmlSerializer 创建 xml,使用相同的布局,虽然(相当多余的,IMO)/Document/Tests/@Count很痛苦 - 我可以告诉你如何如果你真的需要,请解决这个问题。