我有这个xml:
barplot
我想在网格视图中打印它有3列:文件名,文件大小和父文件夹名。
我可以从所有节点获取所有数据,但我无法将文件名连接到适当的父文件夹名称和适当的大小
我试过这样:
<folders>
<Folder>
<Folder_name>test</Folder_name>
<Number_of_files>2</Number_of_files>
<File>
<File_name>DTLite4461-0327</File_name>
<File_size_in_bytes>14682176</File_size_in_bytes>
</File>
<File>
<File_name>TeamViewer_Setup-ioh</File_name>
<File_size_in_bytes>11057224</File_size_in_bytes>
</File>
</Folder>
<Folder>
<Folder_name>podFolder1</Folder_name>
<Number_of_files>1</Number_of_files>
<File>
<File_name>npp.6.9.1.Installer</File_name>
<File_size_in_bytes>4203840</File_size_in_bytes>
</File>
</Folder>
<Folder>
<Folder_name>podFolder2</Folder_name>
<Number_of_files>1</Number_of_files>
<File>
<File_name>d-470sqe</File_name>
<File_size_in_bytes>2582112256</File_size_in_bytes>
</File>
</Folder>
</folders>
使用此代码可正确打印父文件夹名称,但每次都会获取所有文件,但我无法将其连接到文件大小。
我希望在网格视图中得到类似的内容:
XmlDocument doc = new XmlDocument();
doc.Load(xPath);
XmlNodeList folderNodes = doc.SelectNodes(@"/folders/Folder");
int brojac = 0;
foreach (XmlNode folderNode in folderNodes)
{
XmlNodeList fileNameNodes = doc.SelectNodes(@"/folders/Folder/File/File_name");
XmlNodeList fileSizeNodes = doc.SelectNodes(@"/folders/Folder/File/Size");
foreach (XmlNode fileName in fileNameNodes)
{
dgvXML.Rows.Add(fileName.InnerText, folderNode.InnerText, "");
}
}
这是最好的方法吗?
答案 0 :(得分:1)
好吧,因为你问了最好的方法,我建议使用paste special功能,这会让你的生活变得异常轻松。
基本上,您复制xml的示例,使用paste special创建一个类,并使用xmlserializer反序列化对象或对象数组。在msdn链接上完全解释了这一切。你会爱上它。
编辑,因为你遇到了问题:
反序列化do:
using (XmlSerializer serializer = new XmlSerializer(typeof(folders)))
{
StreamReader myReader = new StreamReader(path_to_xml_goes_here);
folders foldersObject = (folders)serializer.Deserialize(myReader);
// Do stuff with the objects here
}
XML类:
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class folders
{
private foldersFolder[] folderField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Folder")]
public foldersFolder[] Folder
{
get
{
return this.folderField;
}
set
{
this.folderField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class foldersFolder
{
private string folder_nameField;
private byte number_of_filesField;
private foldersFolderFile[] fileField;
/// <remarks/>
public string Folder_name
{
get
{
return this.folder_nameField;
}
set
{
this.folder_nameField = value;
}
}
/// <remarks/>
public byte Number_of_files
{
get
{
return this.number_of_filesField;
}
set
{
this.number_of_filesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("File")]
public foldersFolderFile[] File
{
get
{
return this.fileField;
}
set
{
this.fileField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class foldersFolderFile
{
private string file_nameField;
private uint file_size_in_bytesField;
/// <remarks/>
public string File_name
{
get
{
return this.file_nameField;
}
set
{
this.file_nameField = value;
}
}
/// <remarks/>
public uint File_size_in_bytes
{
get
{
return this.file_size_in_bytesField;
}
set
{
this.file_size_in_bytesField = value;
}
}
}
答案 1 :(得分:1)
唉...
您应该重新考虑您的xml结构,因为File
不在“分组”元素内,例如Files
。 Xml结构应如下所示:
Folders
+-Folder
+-Files (you missed that)
+-File
当然,有一种方法可以解决这个问题,但需要使用XDocument class + LiqToXml代替XmlDocument
。
看看例子:
string xcontent = @"<?xml version='1.0' ?>..."; //replace ... with xml content
//i decided to not post entire content of xml due to clarity of code
XDocument xdoc = XDocument.Parse(xcontent);
var data = xdoc.Descendants("Folder")
.Select(x=> new
{
FolderName = x.Element("Folder_name").Value,
Files = x.Descendants("File")
.Select(a=>
Tuple.Create(
a.Element("File_name").Value,
a.Element("File_size_in_bytes").Value)
).ToList()
})
.SelectMany(x=>x.Files.
Select(y=> new
{
FolderName =x.FolderName,
FileName = y.Item1,
FileSize=y.Item2
}))
.ToList();
结果:
FolderName FileName FileSize
test DTLite4461-0327 14682176
test TeamViewer_Setup-ioh 11057224
podFolder1 npp.6.9.1.Installer 4203840
podFolder2 d-470sqe 2582112256
date
查询的作用是什么?
第一个select
语句获取文件夹名称,文件列表属于该文件夹。这样:
FolderName | Files(a list)
---------------------------------------------------
test | Item1(FileName) Item2(FileSize)
|--------------------------------------
| DTLite4461-0327 14682176
| TeamViewer_Setup-ioh 11057224
----------------------------------------------------
... | ... (and so on)
第二个select
语句(SelectMany
)获取数据并将其转置为目标结果集。
尝试!
答案 2 :(得分:0)
试试xml linq:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
const string FILENAME = @"c:\temp\test.xml";
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.Columns.Add("File Name", typeof(string));
dt.Columns.Add("File Size", typeof(string));
dt.Columns.Add("Parent", typeof(string));
XDocument doc = XDocument.Load(FILENAME);
foreach (XElement folder in doc.Descendants("Folder").AsEnumerable())
{
string folder_name = folder.Element("Folder_name").Value;
foreach (XElement file in folder.Descendants("File").AsEnumerable())
{
dt.Rows.Add(new object[] {
file.Element("File_name").Value,
file.Element("File_size_in_bytes").Value,
folder_name
});
}
}
dataGridView1.DataSource = dt;
}
}
}