从层次结构中获取xml数据

时间:2016-07-05 19:44:27

标签: c# xml datagridview

我有这个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, "");
    }
}

这是最好的方法吗?

3 个答案:

答案 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;
        }
    }
}