During one of my recent perl programming projects I needed a way to store configuration for module instance creation. I chose XML as a format for configuration storage and stated looking for a suitable module for reading XML files.

Very soon I discovered there was no existing module that satisfied my requirements:

1. Very concise usage syntax

2. Integrate-able with perl OO

3. Sane treatment of multi-value results

I'll skip some history here, but let's just say that I've ended-up writing proof-of-concept perl module (XML::Twig wrapper) based on the idea of AUTOLOAD'ing methods based on element tag names. I'm well aware of the downsides of this approach, but I suggest you look at the examples below before you start 'flaming' ;)

I know you can get simular results with XPath, but that IMHO is not well suited for configuration parsing.

If anybody is interested I'll try to release the module source on CPAN.

################################################ # XML example: <?xml version='1.0' standalone='yes'?> <config name="MyConfig"> <blah name="X" type="T1"> A </blah> <blah name="X" type="T2"> B </blah> <blah name="Y" type="T3"> C </blah> <blah name="Y" type="T4"> D </blah> <l1 foo1="bar1"> <l2 foo2="bar2"> <l3> Sometext </l3> </l2> </l1> </config> ############################################3 # Module usage example: my $conf = Config::MagicXML::Base->new_from_xml('config.xml'); print $conf->blah('Y')->attr('type'),$/; # prints 'T3' print $conf->blah('Y')->pcdata(),$/; # prints ' C ' print map { $_->pcdata(),$/ } $conf->blah('X'); # prints # A # B print map { $_->attr('type'), "\t", $_->pcdata(), $/ } $conf->blah(); # prints: #T1 A #T2 B #T3 C #T4 D print $conf->l1()->l2()->l3->pcdata(),$/; #prints 'Sometext'
  • Comment on Practical suggestion for accessing configuration data stored in XML format
  • Download Code

Replies are listed 'Best First'.
Re: Practical suggestion for accessing configuration data stored in XML format
by mirod (Canon) on Mar 18, 2003 at 16:14 UTC

    What's wrong with XML::Simple?

    1. XMLin( "file") looks pretty concise to me. Even when using the OO mode it is still pretty short: my $config= XML::Simple->new( forcearray => 1);
    2. I don't know what you mean by Integrate-able with perl OO, you get a clean data structure, what else would you want?
    3. the forcearray option makes XML::Simple behave sanely I believe.
    4. .

    BTW I think your XML structure is not quite optimal, you repeat the X and Y when I believe they should mark a container object (see below).

    Finally I have added a simplify method to XML::Twig that should be more or less equivalent to XMLin. It is very much in alpha state at the moment, but if you grab the development version of XML::Twig from xmltwig.com you can try the code below.

    So here is the result with XML::Simple and with XML::Twig, output using YAML, both for your XML and for an updated version:

    #!/usr/bin/perl -w use XML::Simple; use XML::Twig; use YAML; $/="\n\n"; my $xml= <DATA>; print "Original Version:\n"; print "Loaded using XML::Simple: \n", Dump( XMLin( $xml, forcearray => 1, keyattr => [])); print "Loaded using XML::Twig: \n", Dump( XML::Twig->new->parse( $xml)->simplify( keyattr => [])); $xml=<DATA>; print "Original Version:\n"; print "Loaded using XML::Simple: \n", Dump( XMLin( $xml, forcearray => 1, keyattr => [ 'name', 'type' +])); print "Loaded using XML::Twig: \n", Dump( XML::Twig->new->parse( $xml)->simplify( keyattr => [ 'nam +e', 'type'])); __DATA__ <?xml version='1.0' standalone='yes'?> <config name="MyConfig"> <blah name="X" type="T1"> A </blah> <blah name="X" type="T2"> B </blah> <blah name="Y" type="T3"> C </blah> <blah name="Y" type="T4"> D </blah> <l1 foo1="bar1"> <l2 foo2="bar2"> <l3> Sometext </l3> </l2> </l1> </config> <?xml version='1.0' standalone='yes'?> <config name="MyConfig"> <blah name="X"> <foo type="T1"> A </foo> <foo type="T2"> B </foo> </blah> <blah name="Y"> <foo type="T3"> C </foo> <foo type="T4"> D </foo> </blah> <l1 foo1="bar1"> <l2 foo2="bar2"> <l3> Sometext </l3> </l2> </l1> </config>

      I'm not going to preach that my idea is the only solution, and everybody should use it. I'm sure most people would prefer XML::Simple (which is a good module, but using it can be a bit annoying) or XML::Twig (which is great, and many thanks for it!).

      The replies that I'm getting for my post is exactly the feedback that I wanted to get - in order to see if there is a need for a module like mine.

      However, I do want to note that the problem I wanted to solve was not loading XML file, but quickly accessing the loaded data. With XML::Simple you have to constantly think about the actual data representation in memory (speaking from experience). And the moment you start using 'forcearray' all the initial easiness disappears. From that point on you have to assume that each element is wrapped by an anon. array. (IMHO) Person using module for reading configuration files should not need to think too much about underling data structures or XML.

      I just think that it should be both possible and easy to access parameters in the XML configuration file using just a single line of code. Afterall, it's perl we are talking about ;)

      P.S.: I gave that ugly example intentionally to demonstrate that using method access, you can get get ether just the first element or all of them. This is exactly what XML::Simple lacks.

Re: Practical suggestion for accessing configuration data stored in XML format
by simon.proctor (Vicar) on Mar 18, 2003 at 15:24 UTC
    I'm curious why you chose to roll your own config parser rather than use one of the existing Config::* modules.

    This would certainly be my question if you were to consider submitting to CPAN.

      I needed to represent tree-like configuration, and 1001 CPAN modules for parsing .ini files just didn't cut it

      I needed to describe module instance properties, and ties between instances (think: Application Server for perl module instances)

      I wanted to use method-based access to config options

      I wanted to use XML, so that in some distant feature I could use external 3rd party tools for config file generation

      I did not find anything that looked good in 'OO light' ;)

      Oh and btw, the module in its current state is the after-evolution of the module I wrote for the project

Re: Practical suggestion for accessing configuration data stored in XML format
by Solo (Deacon) on Mar 18, 2003 at 17:07 UTC
    Why not post the module source here as an RFC?

    If it is prohibitively big, extract the code chunks that are important and where the design choices were made.

    My comments on the approach--If I chose to use XML for a config file, I would probably use XPath and XSL Templates to get out the info I need. Using XML, without using XPath or XSLT, is just doing it the hard way, IMHO.

    --Solo

    --
    No. I don't think the Empire had Wookiees in mind when they designed her, Chewie.
      I can not post the code at the moment because of the possible intellectual property issues with my employer. I wanted to see if somebody needs something like this, before I start sorting out the issue with my bosses. The amount of work needed to make the module release worthy is also an issue ;)
        The amount of work needed to make the module release worthy is also an issue ;)

        Just an observation here -- I've found that when working on a module of any significance in the workplace, it pays off to write the module as if you were going to release it to CPAN -- even if you never plan on doing so. By coding with this assumption in mind I am far less likely to cut corners, because there's always a chance that my dirty underwear will be strung out on the line.

        And really, whoever ends up maintaining your code will thank you for the extra attention to detail.

        Matt

Re: Practical suggestion for accessing configuration data stored in XML format
by valdez (Monsignor) on Mar 19, 2003 at 12:13 UTC
Re: Practical suggestion for accessing configuration data stored in XML format
by diotalevi (Canon) on Mar 18, 2003 at 19:04 UTC