【问题标题】:Getting data from xml hierarchically从xml分层获取数据
【发布时间】:2016-07-06 06:11:42
【问题描述】:

我有这个 xml:

<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>

我想在包含 3 列的网格视图中打印它:文件名、文件大小和父文件夹名称。

我可以从所有节点获取所有数据,但我无法将文件名连接到适当的父文件夹名称和适当的大小

我试过这样:

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, "");
    }
}

使用此代码,它可以正确打印出父文件夹名称,但每次都获取所有文件,我无法将其连接到文件大小。

我想在网格视图中得到这样的东西:

> File name ----------- Parent folder name ------ File size
> DTLite4461-0327       test                      14682176
> TeamViewer_Setup-ioh  test                      11057224
> npp.6.9.1.Installer   podFolder1                4203840       
> d-470sqe              podFolder2                2582112256

最好的方法是什么?

【问题讨论】:

  • 我已经回复了similar question。我的建议是将&lt;Files&gt; 子节点添加到&lt;Folder&gt; 节点,然后:&lt;Files&gt;&lt;File&gt;1&lt;/File&gt;&lt;File&gt;2&lt;/File&gt;&lt;/Files&gt; 以便能够获取它们。

标签: c# xml datagridview


【解决方案1】:

好吧,既然您问了最好的方法,我建议您使用paste special 函数,这将使您的生活变得异常轻松。

基本上,您复制 xml 的样本,使用特殊粘贴创建一个类,并使用 xmlserializer 反序列化一个对象或对象数组。这一切都在 msdn 链接上得到了完美的解释。你会喜欢的。

编辑,因为你有问题:

反序列化:

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

【讨论】:

  • 谢谢,但它不适用于我输入的有问题的 xml。
  • @Bopa 我刚试过,效果很好。我会更新答案
【解决方案2】:

嗯... 您应该重新考虑您的 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)获取上述数据并将它们转置到目标结果集中。

试试吧!

【讨论】:

    【解决方案3】:

    试试 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;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2020-01-01
      • 2020-10-06
      • 2021-10-10
      相关资源
      最近更新 更多