Directory Hierarchy

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
Grizzzzzzzzzz
Forum Contributor
Posts: 125
Joined: Wed Sep 02, 2009 8:51 am

Directory Hierarchy

Post by Grizzzzzzzzzz »

I'm needing to write a php script that'll read a flat directories files, and then produce a hierarchical XML view from it.

Each level of the Hierachy is seperated with a ' - ' in the file name, so for example if i had the files

Test - Example - Whatever.xml
Test - Example - Whatever2.xml
Test - Whatever.xml

i'd effectively need an output of something like this;

Code: Select all

<structure>
<layer name="Test">
<layer name ="Example>
<layer name ="Whatever.xml"/>
<layer name ="Whatever2.xml"/>
</layer>
<layer name ="Whatever.xml"/>
</layer>
</structure>
Although in reality there will be 100's of files.

I've tried jumping straight into producing XML from the start, and have decided after a few hours that's somewhat of a optimistic view >_>, so i've gone back to basics and have decided to deal with all actual filenames until the very end, as it should be fairly simple to locate where they go, and slot them in. So i'm currently working on currently getting the structure.

Currently this is what i'm working with;

Code: Select all

 
<?php
    $directory = ".//test";
    $toWrite = "";  
    $handler = opendir($directory);
    $started = false;
    $nodes[] = "";
 
    $count = 0;
    $count2 = 0;
    while ($file = readdir($handler)) 
    {
        if ($file != '.' && $file != '..')
        {
            list($file1, $file2) = split('[.]', $file);
            if ($file2 == "xml")
            {
                $count = 0;
                $intoArray = "";
                
                $pieces = explode(" - ", $file);
                array_pop($pieces);
                
                if (count($pieces) == 0) //ignore single files for now
                {
                
                }
                else
                {
                    while($pieces[$count])
                    {
                        $intoArray .= $pieces[$count].$count."#";
                        $count++;
                    }
                    
                    if ($started) //if array has a value in it, search
                    {
                        if (!(in_array($intoArray, $nodes2))) 
                        {
                            $nodes2[$count2] = $intoArray;
                            $count2++;
                        }
                    }
                    else //skips search phase, only occurs at start
                    {
                        $nodes2[$count2] = $intoArray;
                        $count2++;
                        $started = true;
                    }
                }
            }
        }
    }
    print_r($nodes2);
?>
 
currently in the test directory i have some simple test files;

Test - Test.xml
Test.xml
Test - Test2.xml
Test - Example - Test.xml
Copy - Example - Test.xml
Test - Example - Part - Test.xml
Copy - Test - Test.xml

and the script is outputting
Array
(
[0] => Copy0#Example1#
[1] => Copy0#Test1#
[2] => Test0#Example1#Part2#
[3] => Test0#Example1#
[4] => Test0#
)
The exact match search i have running is working fine, but i've now come to the point where i want to concatenate similar nodes.

for example, i'd want the output to become
Array
(
[0] => Copy0#Example1#Test1#
[1] => Test0#Example1#Part2#
)
Any thoughts/ideas/suggestions?

I've had a look around at other directory -> XML scripts, but all of the ones i've found act on using folders to distinguish between different levels of the hierarchy, rather than characters within the filename.

Cheers for any help offered.
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Re: Directory Hierarchy

Post by pickle »

I'd suggest making a multi-dimensional array.

With each filename, explode() it on ' - ', then use each of the resulting elements (except the last one which is the filename) as keys.

So, if you had these files:

Test - Example - Whatever.xml
Test - Example - Whatever2.xml
Test - Whatever.xml

Your resulting array would be:

Code: Select all

[Test]
  =>[Example]
    =>[Whatever.xml,
       Whatever2.xml]
  =>[Whatever.xml]
That'll be a lot easier to parse into XML.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
User avatar
AbraCadaver
DevNet Master
Posts: 2572
Joined: Mon Feb 24, 2003 10:12 am
Location: The Republic of Texas
Contact:

Re: Directory Hierarchy

Post by AbraCadaver »

I agree with the array statement. Adding the elements using simplexml should be pretty easy. Here's something to get you going, you can either modify it to add children and attributes to a simplexmlelement or build the array and then run over it and create the xml:

Code: Select all

$files = glob('./test/*.xml');
$result = array();
 
foreach($files as $file) {
    $pieces = explode(' - ', $file);
    $name = array_pop($pieces);
 
    $parent = &$result;
 
    foreach($pieces as $piece) {
        if(!isset($parent[$piece])) {
            $parent[$piece] = array();
        }
        $parent = &$parent[$piece];
    }
    $parent[$name] = $file;
}
print_r($result);
mysql_function(): WARNING: This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQLextension should be used. See also MySQL: choosing an API guide and related FAQ for more information.
User avatar
Grizzzzzzzzzz
Forum Contributor
Posts: 125
Joined: Wed Sep 02, 2009 8:51 am

Re: Directory Hierarchy

Post by Grizzzzzzzzzz »

AbraCadaver wrote:I agree with the array statement. Adding the elements using simplexml should be pretty easy. Here's something to get you going, you can either modify it to add children and attributes to a simplexmlelement or build the array and then run over it and create the xml:

Code: Select all

$files = glob('./test/*.xml');
$result = array();
 
foreach($files as $file) {
    $pieces = explode(' - ', $file);
    $name = array_pop($pieces);
 
    $parent = &$result;
 
    foreach($pieces as $piece) {
        if(!isset($parent[$piece])) {
            $parent[$piece] = array();
        }
        $parent = &$parent[$piece];
    }
    $parent[$name] = $file;
}
print_r($result);
Many thanks Abra, tried it and it looks like definately the kind of thing i was looking for.

I'm somewhat unsure on the next step; getting it into XML/getting all the information out of the array, but that's probably because i've only worked with flat arrays where the keys are numerical and i can simply increment my way through them, i'm not sure how i'd be doing the same kind of thing as this, but i'm guessing going away and reading up about multidimensional arrays would be a good start!

As would SimpleXML. Other than the Manual, do you know of any other useful material on the matter?

Cheers
User avatar
Grizzzzzzzzzz
Forum Contributor
Posts: 125
Joined: Wed Sep 02, 2009 8:51 am

Re: Directory Hierarchy

Post by Grizzzzzzzzzz »

Just for reference sake, incase anyone in the future is searching for something similar, working example in a single Array is below;

Code: Select all

 
    $toWrite = "";  
    $handler = opendir(".//test");
    $started = false;
    $nodes[] = "";
    $count = 0;
    $count2 = 0;
    while ($file = readdir($handler)) 
    {
        if ($file != '.' && $file != '..'){
            list($file1, $file2) = split('[.]', $file);
            $count = 0;
            $intoArray = "";
            $pieces = explode(" - ", $file);
            if (!(count($pieces) == 1)){
                $before = $pieces[0];
                array_pop($pieces); 
                if (($before != $after) && ($after != "")){
                    $count2++;
                }               
                $after = $pieces[0];
                while ($pieces[$count]){
                    $pos = strpos($nodes[$count2], "#Start".$count."#".$pieces[$count]."#End".$count."#");
                    if ($pos === false){
                        $nodes[$count2] .= "#Start".$count."#".$pieces[$count]."#End".$count."#";
                    }
                    $count++;
                }   
            }   
        }
    }
 
Post Reply