[英]c#, XML How to cycle through an XML node fetched with XMLNode.SelectSingleNode
I have this class which represent a node TestCase in my XML : 我有这个类,它代表XML中的一个节点TestCase:
public class TestCase
{
[XmlAttribute("name")]
public string name { get; set; }
public string version { get; set; }
public string verdict { get; set; }
public string objective { get; set; }
public string criteria { get; set; }
public string issue { get; set; }
public string clientcomments { get; set; }
public string authoritycomments { get; set; }
public string sdk { get; set; }
}
I use XmlNode.SelectSingleNode to fetch a specific node in my XML. 我使用XmlNode.SelectSingleNode来获取XML中的特定节点。 For info, there are no duplicate nodes (no nodes with the same name attribute) if it matters. 对于信息,如果有问题,则没有重复的节点(没有具有相同名称属性的节点)。
So far, I have this code : 到目前为止,我有以下代码:
public static TestCase FetchNode(string NodeName, string Path)
{
TestCase testcase = new TestCase();
string[] attr = { "name", "version", "verdict", "objective", "criteria"
, "issue", "clientcomments", "authoritycomments", "sdk" };
string[] attrval = { null, null,null,null,null,null,null,null,null};
XmlDocument doc = new XmlDocument();
doc.Load(Path);
XmlNode node = doc.SelectSingleNode("/TestsList/TestCase[@name='" + NodeName + "']");
for (var i = 0; i == attr.Length - 1;i++)
{
attrval[i] = node[attr[i]].InnerText;
}
testcase.name = attrval[0];
testcase.version = attrval[1];
testcase.verdict = attrval[2];
testcase.objective = attrval[3];
testcase.criteria = attrval[4];
testcase.issue = attrval[5];
testcase.clientcomments = attrval[6];
testcase.authoritycomments = attrval[7];
testcase.sdk = attrval[8];
return testcase;
}
However, this code is not scalable at all, if I change my class structure, I would need to change the function because each element of the class are hardcoded in it. 但是,此代码根本无法伸缩,如果我更改类结构,则需要更改功能,因为类的每个元素都在其中进行了硬编码。
This is a wide request, but how could I write this function so if I add or remove a string in the class definition of TestCase, I don`t have to change the function FetchNode. 这是一个广泛的要求,但是我该如何编写此函数,因此,如果在TestCase的类定义中添加或删除字符串,则不必更改FetchNode函数。
Thank you for your time. 感谢您的时间。
You could use XmlSerializer.Deserialize 您可以使用XmlSerializer.Deserialize
Example: 例:
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
public class TestCase
{
[XmlAttribute("name")]
public string name { get; set; }
public string version { get; set; }
public string verdict { get; set; }
public string objective { get; set; }
public string criteria { get; set; }
public string issue { get; set; }
public string clientcomments { get; set; }
public string authoritycomments { get; set; }
public string sdk { get; set; }
}
public class Program
{
public const string XML = @"
<TestCase name='TicketName'>
<name>Jon Nameson</name>
<version>10.1</version>
<verdict>High</verdict>
</TestCase>
";
public static void Main()
{
var doc = new XmlDocument();
doc.LoadXml(XML);
var node = doc.SelectSingleNode("/TestCase");
var serializer = new XmlSerializer(typeof(TestCase));
var testcase = serializer.Deserialize(new StringReader(node.OuterXml)) as TestCase;
Console.WriteLine(testcase.name);
Console.WriteLine(testcase.version);
Console.WriteLine(testcase.verdict);
}
}
You can deserialize directly from your selected XmlNode
by combining XmlSerializer
with XmlNodeReader
using the following extension method: 您可以使用以下扩展方法将XmlSerializer
与XmlNodeReader
结合使用,从而直接从所选XmlNode
反序列化:
public static class XmlNodeExtensions
{
public static T Deserialize<T>(this XmlNode element, XmlSerializer serializer = null)
{
using (var reader = new ProperXmlNodeReader(element))
return (T)(serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
}
class ProperXmlNodeReader : XmlNodeReader
{
// Bug fix from https://stackoverflow.com/questions/30102275/deserialize-object-property-with-stringreader-vs-xmlnodereader
public ProperXmlNodeReader(XmlNode node)
: base(node)
{
}
public override string LookupNamespace(string prefix)
{
return NameTable.Add(base.LookupNamespace(prefix));
}
}
}
This adds an extension method to XmlNode
which invokes XmlSerializer
to deserialize the selected node to an instance of the generic type T
. 这将扩展方法添加到XmlNode
,该方法调用XmlSerializer
将选定的节点反序列化为通用类型T
的实例。
Then do: 然后做:
var testcase = node.Deserialize<TestCase>();
which is identical to: 等同于:
var testcase = XmlNodeExtensions.Deserialize<TestCase>(node);
In your case the expected root element name of your TestCase
class, namely <TestCase>
, matches the actual node name. 在您的情况下,您的TestCase
类的预期根元素名称(即<TestCase>
)与实际节点名称匹配。 If the node name does not match the expected root element name, you can tell XmlSerializer
to expect a different root name by following the instructions in XmlSerializer Performance Issue when Specifying XmlRootAttribute . 如果节点名称与期望的根元素名称不匹配,则可以在指定XmlRootAttribute时遵循XmlSerializer性能问题中的说明,告诉XmlSerializer
期望使用不同的根名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.