0

The goal has been set for me but I have no idea how to get there. Apologies in advance.

Using Perl - I will be receiving a character delimitated file (whose structure I can dictate) and I need to convert it to a XML like file as such

<MyConfig>
   Active = yes
   Refresh = 10 min
 <Includes>
 <Include_Rule_1>
 Active = yes
 Match = /Foo [Bb]ar/
 </Include_Rule_1>
 <Include_Rule_2>
 Active = yes
 Match = /Baz.*/
<Include_Rule_2>
</Include>
<Exclude>
<Exclude_Rule_1>
Exclude = /Bim Bam/
</Exclude_Rule_1>
 </Exclude>
</MyConfig>

So in short it will be XML like (individual values are not surrounded by angle brackets) with 3 sections that are constant but their depth will always be unknown.

I can use CPAN libraries but prefer not to as this script will need to run on individual servers that I have neither access to or control of.

Any ideas ? Starters pointers ? Tips or Tricks ?

Sorry I am so lost here.

eramm
  • 191
  • 16
  • Can you provide a sample input ? – Gilles Quénot Jan 27 '13 at 16:29
  • It is not clear exactly the way you want to generate this XML file, However, take a look on http://stackoverflow.com/questions/4142046/create-xml-file-using-java – Mihai8 Jan 27 '13 at 16:32
  • well since I can dicate how the input can look like i didn't include it as not to limit the solution – eramm Jan 27 '13 at 16:36
  • Take a look at the `split` function for breaking a line into fields, and then the XML::Generator perl module (look in [CPAN](cpan.org)). It's a simple XML output module. – radical7 Jan 27 '13 at 16:52
  • 1
    Welcome to SO. Take some time to look at your sample output.. did you leave out `` by mistake? Why are the first "Active" and "Refresh" properties not part of an "Includes_Rule"? You'll probably want to take a look at the [YAML](http://www.yaml.org/) [standard](http://www.yaml.org/spec/) and Perl modules like [YAML::Tiny](https://metacpan.org/module/YAML::Tiny) – Zaid Jan 27 '13 at 16:55
  • thanks. First Active and Refresh is for the whole profile as opposed to individual sub rules. there may be more than one profile. – eramm Jan 27 '13 at 16:59
  • Is there a reason why you're going for *XML-like* rather than real XML? There is a huge amount of code around to support the generation of XML, but if you are writing your own standard then, no matter how close it may be to an existing format, you are on your own and must code it from scratch. – Borodin Jan 27 '13 at 20:51
  • Surely you can say *something* about the format of your source data? If you can dictate exactly how it looks, then just say you want it in the pseudo-XML format that you show. Job done. – Borodin Jan 27 '13 at 21:00

2 Answers2

0

You can use Template::Toolkit module like in this starter example (you will need to parse your input file first to feed the HASH) :

#!/usr/bin/env perl

use strict; use warnings;
use Template;
my $tt = Template->new;
my $input = {
    MyConfig_Active => "yes",
    MyConfig_refresh => "10 min",
    MyConfig_Include_Rule_1_Active => "yes",
    MyConfig_Include_Rule_1_Match => "/Foo [Bb]ar/"
};
$tt->process('template.tpl', $input)
    || die $tt->error;

template.tpl file :

<MyConfig>
   Active = [% MyConfig_Active %]
   Refresh =  [% MyConfig_refresh %]
 <Includes>
 <Include_Rule_1>
 Active = [% MyConfig_Include_Rule_1_Active %]
 Match = "[% MyConfig_Include_Rule_1_Match %]"
 </Include_Rule_1>
(...)
</MyConfig>

Sample output :

<MyConfig>
   Active = yes
   Refresh =  10 min
 <Includes>
 <Include_Rule_1>
 Active = yes
 Match = "/Foo [Bb]ar/"
 </Include_Rule_1>
(...)
</MyConfig>

See http://template-toolkit.org/docs/tutorial/Datafile.html

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
  • If you want to _thanks_, think to _upvote_. You can _accept_ the response too if you feel that the question is well answerred. That's how stackexchange web sites works. Thanks =) – Gilles Quénot Jan 28 '13 at 18:59
  • I had trid that but SO does not let to upvote unless I have a reputation of at least 15 – eramm Jan 29 '13 at 09:05
0

One option is to use Config::General to generate such a file from a hash you'd populate from the results of the parsed character-delimited file. This file can be easily read back using Config::General to re-populate a hash:

use strict;
use warnings;
use Config::General;

my %config = (
    Active   => 'yes',
    Refresh  => '10 min',
    Includes => {
        Include_Rule_1 => {
            Active => 'yes',
            Match  => '/Foo [Bb]ar/'
        },
        Include_Rule_2 => {
            Active => 'yes',
            Match  => '/Baz.*/'
        }
    },
    Excludes => { 
        Exclude_Rule_1 => { 
            Exclude => '/Bim Bam/'
        }
    }

);

my $conf = new Config::General();

# Save structure to file
$conf->save_file('myConfig.conf', \%config);

Contents of myConfig.conf:

<Excludes Exclude_Rule_1>
    Exclude   /Bim Bam/
</Excludes>
Refresh   10 min
<Includes>
    <Include_Rule_1>
        Match   /Foo [Bb]ar/
        Active   yes
    </Include_Rule_1>
    <Include_Rule_2>
        Match   /Baz.*/
        Active   yes
    </Include_Rule_2>
</Includes>
Active   yes
Kenosis
  • 6,196
  • 1
  • 16
  • 16
  • Config::General looks promising and I have been playing with it all day and reading the cpan docs. 1) it seems to print things in the reverse order. 2) it seems to combine nested blocks "" as opposed to "" and "" 3) it would be nice if there was a switch that added "=" between values 4) it seems to handle the "includes" section well I have no idea why THANKS ! – eramm Jan 28 '13 at 16:56