views:

306

answers:

1

I assume you can use XML::Simple with HTML::FormFu because FromFu uses Config::Any to load it's config data.

However, I can't seem to find any sample xml configs being used with HTML::FormFu. Not only am I getting an error. I'm not sure my xml is structured correctly to create the desired form. For example, on options, formfu wants an array of array refs. But i'm pretty sure this xml will produce an array of hash refs.

I'm not doing something right... Here's the beginning of my xml file:

<?xml version="1.0" encoding="utf-8" ?>
<config>
  <indicator>submit</indicator>
  <elements>
    <element type="FieldSet" name="overrides" label="Over Rides">
     <attributes title="Use these fields to override the csv value with this constant value" />
      <elements>
       <element type="text" name="client" label="Client" />
       <element type="Select" name="bid_type" label="Bid Type">
      <options bid="Bid" />
      <options approved="Approved" />
    </element>
    <element type="text" name="client_pay" label="Client Pay" />
    <element type="text" name="due_date" label="Due Date" />
    <element type="text" name="start_date" label="Start Date" />
    <element type="Radiogroup" name="category" label="Category">
      <options grass_cut_initial="Grass Cut - Initial"/>
      <options grass_cut_recut="Grass Cut - Recut"/>
      <options secure="Secure"/>
      <options winterization="Winterization"/>
      <options rehab="Rehab" />
      <options custom="Custom"/>
    </element>
    <element type="text" name="contractor" label="Contractor" />
    <element type="text" name="contractor_pay" label="Contractor Pay" />
  </elements>
</element>

I'm getting this error:

[debug] Catalyst::Controller::HTML::FormFu::Action::FormConfig loading config file 'workorders/import'
[error] Caught exception in myapsjobs::Controller::WorkOrders->import "Error parsing /home/jon/aps-dev/myapsjobs/root/forms/workorders/import.xml: /home/jon/aps-dev/myapsjobs/root/forms/workorders/import.xml:38: parser error : Premature end of data in tag config line 1
 at /usr/local/share/perl/5.10.0/HTML/FormFu/ObjectUtil.pm line 502"
+2  A: 

Trying to create an XML file that XML::Simple will parse into a specific data structure can be a real pain. I find the easiest way to handle this is to start with the data structure you want, run it through XMLout, then modify the resulting XML as you see fit.

use strict;
use warnings;
use XML::Simple;

my $config = { 
    'indicator' => 'edit',
    'elements' => [
        {   
            'name' => 'overrides',
            'label' => 'Over Rides',
            'type' => 'Fieldset',
            'attributes' => {
                'title' => 'Use these fields to override the csv value with this constant value',
            },
            'elements' => [
                {   
                    'type' => 'text',
                    'name' => 'client',
                    'label' => 'Client',
                },  
                {
                    'type' => 'Select',
                    'name' => 'bidy_type',
                    'label' => 'Bid Type',
                    'options' => [
                        [ 'bid' => 'Bid' ],
                        [ 'approved' => 'Approved' ],
                    ],
                },
                {
                    'type' => 'text',
                    'name' => 'client_pay',
                    'label' => 'Client Pay',
                },
                {
                    'type' => 'text',
                    'name' => 'due_date',
                    'label' => 'Due Date',
                },
                {
                    'type' => 'text',
                    'name' => 'start_date',
                    'label' => 'Start Date',
                },
                {
                    'type' => 'Radiogroup',
                    'name' => 'category',
                    'label' => 'Category',
                    'options' => [
                        [ 'grass_cut_initial' => 'Grass Cut - Initial' ],
                        [ 'grass_cut_recut' => 'Grass Cut - Recut' ],
                        [ 'secure' => 'Secure' ],
                        [ 'winterization' => 'Winterization' ],
                        [ 'rehab' => 'Rehab' ],
                        [ 'custom' => 'Custom' ],
                    ],
                },
                {
                    'type' => 'text',
                    'name' => 'contractor',
                    'label' => 'Contractor',
                },
                {
                    'type' => 'text',
                    'name' => 'contractor_pay',
                    'label' => 'Contractor Pay',
                },
            ],
        },
    ],
};
my $xml = XMLout($config, 'KeyAttr' => []);

print "$xml\n";

Result

<opt indicator="edit">
  <elements label="Over Rides" name="overrides" type="Fieldset">
    <attributes title="Use these fields to override the csv value with this constant value" />
    <elements label="Client" name="client" type="text" />
    <elements label="Bid Type" name="bidy_type" type="Select">
      <options>
        <anon>bid</anon>
        <anon>Bid</anon>
      </options>
      <options>
        <anon>approved</anon>
        <anon>Approved</anon>
      </options>
    </elements>
    <elements label="Client Pay" name="client_pay" type="text" />
    <elements label="Due Date" name="due_date" type="text" />
    <elements label="Start Date" name="start_date" type="text" />
    <elements label="Category" name="category" type="Radiogroup">
      <options>
        <anon>grass_cut_initial</anon>
        <anon>Grass Cut - Initial</anon>
      </options>
      <options>
        <anon>grass_cut_recut</anon>
        <anon>Grass Cut - Recut</anon>
      </options>
      <options>
        <anon>secure</anon>
        <anon>Secure</anon>
      </options>
      <options>
        <anon>winterization</anon>
        <anon>Winterization</anon>
      </options>
      <options>
        <anon>rehab</anon>
        <anon>Rehab</anon>
      </options>
      <options>
        <anon>custom</anon>
        <anon>Custom</anon>
      </options>
    </elements>
    <elements label="Contractor" name="contractor" type="text" />
    <elements label="Contractor Pay" name="contractor_pay" type="text" />
  </elements>
</opt>

Not exactly the XML you would expect, but it gets the job done. You can also double check that this works by running it back through XMLin and examining the resulting data structure:

use strict;
use warnings;
use XML::Simple;
use Data::Dumper;

my $xml = '...';
my $config = XMLin($xml, 'KeyAttr' => []);
print Dumper($config);

The reason I use the KeyAttr option is because of this caveat:

If you wish to 'round-trip' arbitrary data structures from Perl to XML and back to Perl, then you should probably disable array folding (using the KeyAttr option) both with XMLout() and with XMLin().

Also, I can't seem to find a way to pass options to Config::Any through load_config_file (I haven't spent much time hunting through the docs for HTML::FormFu though). This means you might have to use XML::Simple yourself to get the data structure to pass to populate.


As you can see, an XML config file really isn't the easiest approach when working with HTML::FormFu. If you're open to other approaches, I would suggest using something that has a much better mapping to Perl data structures, like YAML (probably one of the reasons why it's used in the documentation examples). Personally, I just use Perl to create my forms and stick the code/config in a module.

bish