在 C# 中解析 XML 数据并显示到 ListBox
Posted
技术标签:
【中文标题】在 C# 中解析 XML 数据并显示到 ListBox【英文标题】:Parsing XML data in C# and show into ListBox 【发布时间】:2016-04-21 00:38:25 【问题描述】:我正在尝试使用 Visual Studio 解析 C# 中的 XML 文件并在 ListBox 中显示数据,但在处理嵌套的 XML 文件时我不知道如何解析它。
这是来自 XML 文件的代码:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE root [
<!ELEMENT root (Persons*)>
<!ELEMENT Persons (name)>
<!ELEMENT IsMale (#PCDATA)>
<!ELEMENT Age (#PCDATA)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT LikedPerson (name)>
]>
<root>
<Persons name ="Bob">
<IsMale>true</IsMale>
<Age>30</Age>
<LikedPerson name ="Iulia">
<IsMale>false</IsMale>
<Age>32</Age>
</LikedPerson>
</Persons>
</root>
我用 C# 编写的代码成功地只为我返回了每个人的姓名、性别和年龄,但我不知道如何编写以显示 person_liked:
private void LoadPersons()
XmlDocument doc = new XmlDocument();
doc.Load("Baza_de_cunostinte.xml");
foreach (XmlNode node in doc.DocumentElement)
string name = node.Attributes[0].Value;
int age = int.Parse(node["Age"].InnerText);
bool isMale = bool.Parse(node["IsMale"].InnerText);
// Persons likedPerson.name = Persons.node.Attributes[0].Value ?
// .....
listBox.Items.Add(new Persons(name, age, isMale, likedPerson));
private void listBox_SelectedIndexChanged(object sender, EventArgs e)
if (listBox.SelectedIndex != -1)
propertyGrid1.SelectedObject = listBox.SelectedItem;
这是 Persons.cs 的定义:
class Persons
public string Name get; private set;
public int Age get; private set;
public bool IsMale get; private set;
public Persons LikedPerson get; private set;
public Persons(string name, int age, bool isMale, Persons likedPerson)
Name = name;
Age = age;
IsMale = isMale;
LikedPerson = likedPerson;
【问题讨论】:
LikedPerson
可以出现多次吗?
你还需要为此更新你的类,因为它现在只能在 CLR 对象中出现一次。
【参考方案1】:
XmlSerializer mySerializer = new XmlSerializer(typeof(Persons));
// Create a FileStream or textreader to read the xml data.
FileStream myFileStream = new FileStream("xmldatafile.xml", FileMode.Open);
var person = (Persons) mySerializer.Deserialize(myFileStream);
您还需要为 Persons 类添加不带参数的构造函数。
【讨论】:
它在 XmlSerializer... 行上给了我以下错误:Proiect_SBC.Persons 由于其保护级别而无法访问。只能处理公共类型。 公开类定义:public class Persons... 现在我在 var person = (Persons) mySerializer.Deserialize(myFileStream); 上有一个错误。 ->> "XML 文档中存在错误 (10, 2)。" 这是一个不错的建议@RadinGospodinov,但如果不对类(或 XML)进行重大改造,将无法工作......【参考方案2】:按照建议,最自然的方法是使用XmlSerializer
,但要这样做,您必须稍微重构您的类:
[XmlType(Namespace="", TypeName="root")]
public class PersonCollection
[XmlElement(Namespace="", ElementName="Persons")]
public List<Persons> People get; set;
public class Persons
[XmlAttribute(AttributeName="name")]
public string Name get; set;
public int Age get; set;
public bool IsMale get; set;
public Persons LikedPerson get; set;
public Persons()
public Persons(string name, int age, bool isMale, Persons likedPerson)
Name = name;
Age = age;
IsMale = isMale;
LikedPerson = likedPerson;
然后你可以这样做:
XmlSerializer ser = new XmlSerializer(typeof(PersonCollection));
PersonCollection pc = (PersonCollection)ser.Deserialize(File.OpenRead("Baza_de_cunostinte.xml"));
foreach (Persons p in pc.People)
// you now have a fully populated object
pc.People
列表将包含您的 Persons
对象。
【讨论】:
【参考方案3】:@user3063909,
1- 为 XML 定义使用 XSD。例如:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="Persons" maxOccurs="unbounded" minOccurs="0" type="Persons"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Persons">
<xs:sequence>
<xs:element type="xs:string" name="IsMale"/>
<xs:element type="xs:int" name="Age"/>
<xs:element name="LikedPerson" type="Persons"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" />
</xs:complexType>
</xs:schema>
2- Persons 类应如下所示:
namespace ***
public class Root
[XmlElement("Persons")]
public List<Persons> Persons get; set;
public class Persons
public string IsMale get; set;
public int Age get; set;
public Persons LikedPerson get; set;
[XmlAttribute("Name")]
public string Name get; set;
3- 序列化器类:
namespace ***
public class XmlSerializerHelper<T> where T : class
private readonly XmlSerializer _serializer;
public XmlSerializerHelper()
_serializer = new XmlSerializer(typeof(T));
public T BytesToObject(byte[] bytes)
using (var memoryStream = new MemoryStream(bytes))
using (var reader = new XmlTextReader(memoryStream))
return (T)_serializer.Deserialize(reader);
4- 最后,这样称呼它:
var fileBytes = File.ReadAllBytes("C:/xml.xml");
var persons = new XmlSerializerHelper<Root>().BytesToObject(fileBytes);
结果将是带有人员列表的根类。
干杯。
【讨论】:
【参考方案4】:您可以像现在一样获取 LikedPerson 节点并获取它的名称/年龄。为了避免代码重复,您可以创建一个方法,该方法接受 XmlNode,递归解析它并返回一个 Person。但更好的方法是使用XmlSerializer
foreach (XmlNode node in doc.DocumentElement)
string name = node.Attributes[0].Value;
int age = int.Parse(node["Age"].InnerText);
bool isMale = bool.Parse(node["IsMale"].InnerText);
var likedPerson = node.SelectSingleNode("LikedPerson");
if (likedPerson != null)
string name = likedPerson.Attributes[0].Value;
//age, gender, etc.
【讨论】:
我还添加了“private System.Xml.XmlNode likePerson;”在 Persons.cs 中,现在它在 PropertyGrid 中向我显示“LikedPerson”,但它旁边没有显示任何内容......(如姓名、年龄......) 你能更新你的代码吗?我会尝试重现您的问题。 我无法评论另一个答案:XML 文档中存在错误 (10, 2)。您的根元素不是“Persons”,这就是您收到此错误的原因。以上是关于在 C# 中解析 XML 数据并显示到 ListBox的主要内容,如果未能解决你的问题,请参考以下文章
通过 ajax 将 XML 属性与 Elements 一起发送到 C# 控制器方法并解析以保存