Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Generating XML from a template

by piyush.shourie (Beadle)
on Dec 14, 2004 at 04:46 UTC ( #414598=perlquestion: print w/replies, xml ) Need Help??
piyush.shourie has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

I need to write a script wherein I take an XML template file and hash of values for that template as input parameters, and return the XML file (XML template populated with values).

This is a generic requirement, and I am not sure how to handle such requirement. Please suggest whether I need to do extensive pattern matching to populate the template, or is there any Perl Module available that may help me out.

Thanks in advance,

Replies are listed 'Best First'.
Re: Generating XML from a template
by jZed (Prior) on Dec 14, 2004 at 04:52 UTC
Re: Generating XML from a template
by qq (Hermit) on Dec 14, 2004 at 10:03 UTC

    There is nothing wrong with the templating approach, but if you are not familiar with them, you should glance at the many XML modules on CPAN as well.

    You could either create the entire xml as needed, or have an xml template that you parse, then just change the values of whatever nodes needed. This may give you more flexibility in some cases.

    Example using XML::Twig:

    #!/usr/bin/perl use strict; use warnings; use XML::Twig; my $xml = do { local $/; <DATA>; }; my %data = ( name => 'Billy', age => 12, ); my $t = XML::Twig->new( twig_handlers => { name => sub { $_->set_text( $data{name} ); }, age => sub { $_->set_text( $data{age} ); }, }, pretty_print => 'indented', ); $t->parse( $xml ); $t->flush; __DATA__ <?xml version="1.0" ?> <root> <name>THIS CHANGES</name> <static>blah blah blah</static> <static>blah blah blah</static> <age>THIS CHANGES</age> </root>
Re: Generating XML from a template
by edan (Curate) on Dec 14, 2004 at 07:32 UTC

    I also think HTML::Template will probably do the job. The only thing that might bite you is XML escaping - as the name implies, the module is intended for HTML documents, not XML. But it does support HTML escaping, and that will probably suffice. Here's a little example to get you started.

    # file use HTML::Template; use strict; use warnings; my $template = HTML::Template->new(filename => 'test.tmpl'); # params $template->param(tag1 => '<tag1_test_value>'); $template->param(tag2 => '<tag2_test_value>'); print $template->output(); # file test.tmpl <root> <tag1><TMPL_VAR ESCAPE=HTML tag1></tag1> <tag2><TMPL_VAR ESCAPE=HTML tag2></tag2> </root> # output <root> <tag1>&lt;tag1_test_value&gt;</tag1> <tag2>&lt;tag2_test_value&gt;</tag2> </root>

      Hi Edan,

      It looks like a very comfortable solution to the problem posed. However if you deeply look at the real-life XML scenario, an XML may have multiple nodes with the same name. For example:

      <root> <tag1> <commontag>XXX</commontag> </tag1> <tag2> <commontag>YYY</commontag> </tag2> <tag3> <commontag>ZZZ</commontag> </tag3> </root>

      In such a complex scenario, we might not be able to use the solution suggested here.
      However since I was short on time, I have used the XML::XPath module to populate the template as XPath queries identify each node and attribute uniquely.

      There may be some better solution to the problem, and would really appreciate if someone can share it with me.


        Hi. I'm not sure I understand what is so complex about your scenario. Perhaps you can provide more exact details about your input and output in your real-life scenario, and then we'd have some common ground to go on.

        To get your output, you can easily modify the code I gave you:

        # file use HTML::Template; use strict; use warnings; my $template = HTML::Template->new(filename => 'test.tmpl'); # params $template->param(tag1_common => 'XXX'); $template->param(tag2_common => 'YYY'); $template->param(tag3_common => 'ZZZ'); print $template->output(); # file test.tmpl <root> <tag1> <commontag><TMPL_VAR ESCAPE=HTML tag1_common></commontag> </tag1> <tag2> <commontag><TMPL_VAR ESCAPE=HTML tag2_common></commontag> </tag2> <tag3> <commontag><TMPL_VAR ESCAPE=HTML tag3_common></commontag> </tag3> </root> # output <root> <tag1> <commontag>XXX</commontag> </tag1> <tag2> <commontag>YYY</commontag> </tag2> <tag3> <commontag>ZZZ</commontag> </tag3> </root>

        But perhaps what you're really asking about is the ability to have loops in your template. Well, if you would read the docs, you'd find you can do that too! Perhaps you're looking for something along these lines:

        # file use HTML::Template; use strict; use warnings; my $template = HTML::Template->new(filename => 'test.tmpl'); my @xml = ( { parent => 'tag1', common_value => 'XXX', }, { parent => 'tag2', common_value => 'YYY', }, { parent => 'tag3', common_value => 'XXX', }, ); # params $template->param( loop => \@xml ); print $template->output(); # file test.tmpl <root> <TMPL_LOOP loop> <<TMPL_VAR parent>> <commontag><TMPL_VAR ESCAPE=HTML common_value></commontag> </<TMPL_VAR parent>> </TMPL_LOOP> </root> # output <root> <tag1> <commontag>XXX</commontag> </tag1> <tag2> <commontag>YYY</commontag> </tag2> <tag3> <commontag>XXX</commontag> </tag3> </root>

        Again, I'm just guessing here, since you're not providing enough detail about your actual needs.


Re: Generating XML from a template
by csuhockey3 (Curate) on Dec 14, 2004 at 06:14 UTC
    If you have control over the XML templating, a nice option might be using xml::template for both. If not, another alternative would be using HTML::Template to populate the XML.

    update: credit to jZed's response.
Re: Generating XML from a template
by davorg (Chancellor) on Dec 23, 2004 at 11:04 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://414598]
Approved by Old_Gray_Bear
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (10)
As of 2018-03-22 14:46 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (277 votes). Check out past polls.