C# 解析 XML 并将其存储到 Class
C# Parsing an XML and storing it into a Class
我需要解析一个 XML 并将其存储到一个 class 中,但它让我头疼的事情比我愿意承认的要多得多。
假设 XML 看起来像这样:
<PARENT>
<ITEM>
<DATA1>
<A>12345</A>
<B>12345</B>
<C>12345</C>
</DATA1>
<DATA2>
<D>12345</D>
<E>12345</E>
<F>12345</F>
</DATA2>
<DATA3>
<ITEM>
<G/>
<H>111</H>
<I>223</I>
</ITEM>
<ITEM>
<G/>
<H>2342</H>
<I>25323</I>
</ITEM>
<ITEM>
<G>185</G>
<H>63611</H>
<I/>
</ITEM>
</DATA3>
</ITEM>
<ITEM>
<DATA1>
<A>23456</A>
<B>23456</B>
<C>23456</C>
</DATA1>
</ITEM>
</PARENT>
我面临的第一个问题是名称“ITEM”不仅作为“PARENT[=42”的子节点出现=]”,但也在“DATA3”下再次使用,所以如果我像这样搜索
XDocument doc = XDocument.Parse(tmp);
IEnumerable<XElement> tmp_list = doc.Descendants(XName.Get("ITEM"));
它会给我五个结果,而不是两个。
我也已经尝试过这样搜索路径 //PARENT/ITEM 的方法:
string file = @"C:\temp\test.xml";
var document = XDocument.Load(file);
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("empty", "random:namespace:name");
IEnumerable<XElement> ele_list = document.XPathSelectElements("//PARENT//ITEM", namespaceManager);
但它也不起作用,因为它还会获取所有孙节点...
问题 1)如何正确地将搜索限制在顶级节点?
问题 2) 我将如何以最有效的方式继续并将整个事情存储到 class 中?我试过将完整的 XML 响应复制粘贴到像 http://xmltocsharp.azurewebsites.net/ 这样的网站,但他们似乎都在为重复的名称“ITEM”而苦苦挣扎,基本上创建一个class 合并了所有不同的“ITEM”子节点。是否有可能以简单有效的方式填写项目列表?我希望基本上有一些类似的东西:
List<DataItem> grd_list = doc.Descendants(XName.Get("ITEM"))
.Select(f => new DataItem()
{
DATA1 = f.Element(XName.Get("DATA1")).Document.ToString(),
DATA2 = f.Element(XName.Get("DATA2")).Document.ToString(),
//etc.....
}).ToList();
但我知道上面的 LINQ 必须比这更复杂,因为 DATA1 等也需要有子节点。
您可以使用序列化程序 XML(这只是您 xml 之后的一个示例)
您可以通过在 class ITEM 的定义中定义所有情况来避免 item 的问题。因此项目不存在(G、H、I 或 DATA1、DATA2.. 将为空)。
using System.Xml.Serialization;
XmlSerializer serializer = new XmlSerializer(typeof(PARENT));
using (StringReader reader = new StringReader(xml))
{
var test = (PARENT)serializer.Deserialize(reader);
}
:
:
[XmlRoot(ElementName = "DATA1")]
public class DATA1
{
[XmlElement(ElementName = "A")]
public string A { get; set; }
[XmlElement(ElementName = "B")]
public string B { get; set; }
[XmlElement(ElementName = "C")]
public string C { get; set; }
}
[XmlRoot(ElementName = "DATA2")]
public class DATA2
{
[XmlElement(ElementName = "D")]
public string D { get; set; }
[XmlElement(ElementName = "E")]
public string E { get; set; }
[XmlElement(ElementName = "F")]
public string F { get; set; }
}
[XmlRoot(ElementName = "ITEM")]
public class ITEM
{
[XmlElement(ElementName = "G")]
public string G { get; set; }
[XmlElement(ElementName = "H")]
public string H { get; set; }
[XmlElement(ElementName = "I")]
public string I { get; set; }
[XmlElement(ElementName = "DATA1")]
public DATA1 DATA1 { get; set; }
[XmlElement(ElementName = "DATA2")]
public DATA2 DATA2 { get; set; }
[XmlElement(ElementName = "DATA3")]
public DATA3 DATA3 { get; set; }
}
[XmlRoot(ElementName = "DATA3")]
public class DATA3
{
[XmlElement(ElementName = "ITEM")]
public List<ITEM> ITEM { get; set; }
}
[XmlRoot(ElementName = "PARENT")]
public class PARENT
{
[XmlElement(ElementName = "ITEM")]
public List<ITEM> ITEM { get; set; }
}
我需要解析一个 XML 并将其存储到一个 class 中,但它让我头疼的事情比我愿意承认的要多得多。
假设 XML 看起来像这样:
<PARENT>
<ITEM>
<DATA1>
<A>12345</A>
<B>12345</B>
<C>12345</C>
</DATA1>
<DATA2>
<D>12345</D>
<E>12345</E>
<F>12345</F>
</DATA2>
<DATA3>
<ITEM>
<G/>
<H>111</H>
<I>223</I>
</ITEM>
<ITEM>
<G/>
<H>2342</H>
<I>25323</I>
</ITEM>
<ITEM>
<G>185</G>
<H>63611</H>
<I/>
</ITEM>
</DATA3>
</ITEM>
<ITEM>
<DATA1>
<A>23456</A>
<B>23456</B>
<C>23456</C>
</DATA1>
</ITEM>
</PARENT>
我面临的第一个问题是名称“ITEM”不仅作为“PARENT[=42”的子节点出现=]”,但也在“DATA3”下再次使用,所以如果我像这样搜索
XDocument doc = XDocument.Parse(tmp);
IEnumerable<XElement> tmp_list = doc.Descendants(XName.Get("ITEM"));
它会给我五个结果,而不是两个。
我也已经尝试过这样搜索路径 //PARENT/ITEM 的方法:
string file = @"C:\temp\test.xml";
var document = XDocument.Load(file);
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("empty", "random:namespace:name");
IEnumerable<XElement> ele_list = document.XPathSelectElements("//PARENT//ITEM", namespaceManager);
但它也不起作用,因为它还会获取所有孙节点...
问题 1)如何正确地将搜索限制在顶级节点?
问题 2) 我将如何以最有效的方式继续并将整个事情存储到 class 中?我试过将完整的 XML 响应复制粘贴到像 http://xmltocsharp.azurewebsites.net/ 这样的网站,但他们似乎都在为重复的名称“ITEM”而苦苦挣扎,基本上创建一个class 合并了所有不同的“ITEM”子节点。是否有可能以简单有效的方式填写项目列表?我希望基本上有一些类似的东西:
List<DataItem> grd_list = doc.Descendants(XName.Get("ITEM"))
.Select(f => new DataItem()
{
DATA1 = f.Element(XName.Get("DATA1")).Document.ToString(),
DATA2 = f.Element(XName.Get("DATA2")).Document.ToString(),
//etc.....
}).ToList();
但我知道上面的 LINQ 必须比这更复杂,因为 DATA1 等也需要有子节点。
您可以使用序列化程序 XML(这只是您 xml 之后的一个示例)
您可以通过在 class ITEM 的定义中定义所有情况来避免 item 的问题。因此项目不存在(G、H、I 或 DATA1、DATA2.. 将为空)。
using System.Xml.Serialization;
XmlSerializer serializer = new XmlSerializer(typeof(PARENT));
using (StringReader reader = new StringReader(xml))
{
var test = (PARENT)serializer.Deserialize(reader);
}
:
:
[XmlRoot(ElementName = "DATA1")]
public class DATA1
{
[XmlElement(ElementName = "A")]
public string A { get; set; }
[XmlElement(ElementName = "B")]
public string B { get; set; }
[XmlElement(ElementName = "C")]
public string C { get; set; }
}
[XmlRoot(ElementName = "DATA2")]
public class DATA2
{
[XmlElement(ElementName = "D")]
public string D { get; set; }
[XmlElement(ElementName = "E")]
public string E { get; set; }
[XmlElement(ElementName = "F")]
public string F { get; set; }
}
[XmlRoot(ElementName = "ITEM")]
public class ITEM
{
[XmlElement(ElementName = "G")]
public string G { get; set; }
[XmlElement(ElementName = "H")]
public string H { get; set; }
[XmlElement(ElementName = "I")]
public string I { get; set; }
[XmlElement(ElementName = "DATA1")]
public DATA1 DATA1 { get; set; }
[XmlElement(ElementName = "DATA2")]
public DATA2 DATA2 { get; set; }
[XmlElement(ElementName = "DATA3")]
public DATA3 DATA3 { get; set; }
}
[XmlRoot(ElementName = "DATA3")]
public class DATA3
{
[XmlElement(ElementName = "ITEM")]
public List<ITEM> ITEM { get; set; }
}
[XmlRoot(ElementName = "PARENT")]
public class PARENT
{
[XmlElement(ElementName = "ITEM")]
public List<ITEM> ITEM { get; set; }
}