1

I'll cut straight to the chase!

Here's my XML, it contains a folder structure and a list of files with their md5 hashes.

<?xml version="1.0" encoding="utf-8"?>
<dir name="Root">
  <dir name="Folder01">
    <dir name="SubFolder01">
      <file md5="77c34f94b0827a2a511b7c9113fd8e31" name="file01.lua" />
      <file md5="47e656c824a3de6fd6bdf7429045b570" name="file02.lua" />
      <file md5="8c9d3b467fbb3173bebed99bae400995" name="file03.lua" />
      <file md5="ade88ad29426e49c9a81e923bb428445" name="file04.lua" />
    </dir>
    <dir name="SubFolder02">
      <dir name="SubFolder03">
        <dir name="SubFolder04">
          <file md5="e1a8566380b2a4256e1792b48705058c" name="file.png" />
        </dir>
      </dir>
    </dir>
  </dir>
  <dir name="Folder02">
    <dir name="SubFolder01">
      <file md5="12f6a2a9e85817fdf6f791f1b0fe37b3" name="File01.lua" />
    </dir>
  </dir>
</dir>

I would like to read in this XML and generate a list of files with their md5's like this...

Root\Folder01\SubFolder01\file01.lua, 77c34f94b0827a2a511b7c9113fd8e31
Root\Folder01\SubFolder01\file02.lua, 47e656c824a3de6fd6bdf7429045b570
Root\Folder01\SubFolder01\file03.lua, 8c9d3b467fbb3173bebed99bae400995
Root\Folder01\SubFolder01\file04.lua, ade88ad29426e49c9a81e923bb428445
Root\Folder01\SubFolder02\SubFolder03\SubFolder04\file.png, e1a8566380b2a4256e1792b48705058c
Root\Folder02\SubFolder01\File01.lua, 12f6a2a9e85817fdf6f791f1b0fe37b3

This is the (broken) code I have so far

var SingleFiles = SourceXMLFile.Descendants("dir")

               .Select(x => new
               {
                   FileName = (string)x.Attribute("name"),
                   md5 = (string)x.Attribute("md5")
               });

I realise I neeed to iterate through the nodes and descendants to build the Filename string based on parents etc. but I'm a little burnt out at the moment (having tried numerous ways!) if anyone could help I'd be extremely grateful.

UPDATE: While the answer given by Ron.B.I. may not have actually been an answer, it did give me a push in the right direction to figure it out myself.

XmlReader rdr = XmlReader.Create(new System.IO.StringReader(XMLasString));
            string newPath = "";
            while (rdr.Read())
            {
                if (rdr.NodeType == XmlNodeType.Element)
                {
                    if (rdr.LocalName == "file")
                        Console.WriteLine(newPath + rdr.GetAttribute(1) + " " + rdr.GetAttribute(0));
                    else
                        newPath = newPath + (rdr.GetAttribute(0)) + Path.DirectorySeparatorChar;
                }
            }

I'm going to go through the other answers now and mark the 'best' one. Thanks for all your help.

1

3 Answers 3

3
var doc = XDocument.Parse(xml);
string[] filesAndMD5 = doc.Descendants("file")
                          .Select(node => GetFullPath(node) + ", " + node.Attribute("md5").Value)
                          .ToArray();                             

filesAndMD5.ForEach(Console.WriteLine);

public string GetFullPath(XElement node)
{
    string res = "";

    while(node != null)
    {
        res = Path.Combine(node.Attribute("name").Value, res);
        node = node.Parent;
    }
    return res;
}

prints:

Root\Folder01\SubFolder01\file01.lua, 77c34f94b0827a2a511b7c9113fd8e31
Root\Folder01\SubFolder01\file02.lua, 47e656c824a3de6fd6bdf7429045b570
Root\Folder01\SubFolder01\file03.lua, 8c9d3b467fbb3173bebed99bae400995
Root\Folder01\SubFolder01\file04.lua, ade88ad29426e49c9a81e923bb428445
Root\Folder01\SubFolder02\SubFolder03\SubFolder04\file.png, e1a8566380b2a4256e1792b48705058c
Root\Folder02\SubFolder01\File01.lua, 12f6a2a9e85817fdf6f791f1b0fe37b3
Sign up to request clarification or add additional context in comments.

Comments

1
var xDoc = XDocument.Parse(xmlstring);
var files = xDoc.Descendants("file")
                .Select(f => String.Format("{0} {1}",
                                            String.Join("/",GetPath(f).Reverse()),
                                            f.Attribute("md5").Value))
                .ToList();


IEnumerable<string> GetPath(XElement e)
{
    while(e!=null) {
        yield return e.Attribute("name").Value;
        e = e.Parent;
    }
}

Comments

0

A slighty different approach:

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;

namespace Demo
{
    class Program
    {
        void run()
        {
            XDocument doc = XDocument.Load("C:\\TEST\\TEST.XML");
            var filenames = ExtractFilenamesAndHashes(doc);
            filenames.Print();
        }

        public IEnumerable<string> ExtractFilenamesAndHashes(XDocument doc)
        {
            return extractFilenamesAndHashes(doc.Root, doc.Root.Attribute("name").Value);
        }

        IEnumerable<string> extractFilenamesAndHashes(XElement root, string path)
        {
            foreach (var folder in root.Elements("dir"))
                foreach (var filename in extractFilenamesAndHashes(folder, Path.Combine(path, folder.Attribute("name").Value)))
                    yield return filename;

            foreach (var file in root.Elements("file"))
                yield return Path.Combine(path, file.Attribute("name").Value + ", " + file.Attribute("md5").Value);
        }

        static void Main()
        {
            new Program().run();
        }
    }

    static class DemoUtil
    {
        public static void Print(this object self)
        {
            Console.WriteLine(self);
        }

        public static void Print(this string self)
        {
            Console.WriteLine(self);
        }

        public static void Print<T>(this IEnumerable<T> self)
        {
            foreach (var item in self)
                Console.WriteLine(item);
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.