santellij has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have a quick question: I wanted to write a basic method that would take one argument and will write any basic XML element like:

<year>1999</year>
This is assuming that any tag has the value for that element in a variable by the same name. I mean, $year = "1999"; is already set. I can't seam to get the value for the tag I'm trying to write. Here's my method but what do I use to access $year (for this example).
sub writeBasicTag { my $tag = $_[0]; $writer->startTag($tag); $writer->characters(XXX); $writer->endTag($tag); }

Am I missing something obvious... is it Friday?
TIA,

Replies are listed 'Best First'.
Re: indirectly accessing variable
by davorg (Chancellor) on Jul 11, 2003 at 15:51 UTC

    You want symbolic references.

    $writer->characters($$tag);

    But these are a really bad idea for very many reasons. In fact when you "use strict" (and I hope you use strict) symbolic references will trigger a fatal error.

    You're better off using a hash.

    $writer->characters($vars{$tag});
    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      Thanks! I tried the $$tag and got an error. I don't know why I didn't think of a hash -- That did the trick.
Re: indirectly accessing variable
by tall_man (Parson) on Jul 11, 2003 at 15:53 UTC
    You would do better to put the values in a hash, like this:
    my %xml_values = (); $xml_values{year} = '1999'; sub writeBasicTag { my $tag = $_[0]; $writer->startTag($tag); $writer->characters($xml_values{$tag}); $writer->endTag($tag); }
    There are all sorts of articles around about why it's a bad idea to access variables by name through other variables.
Re: indirectly accessing variable
by Zaxo (Archbishop) on Jul 11, 2003 at 16:01 UTC

    If I understand correctly, you want to call that like, writeBasicTag( 'year' ); , and produce XML with data from $year. You are trying to do it with symbolic references, which will work under no strict 'refs'; , but is not best practice. If you change 'XXX' to '$$tag', you'll get what you want, but there is a better way.

    The rule of thumb is: When you want to use symrefs, use a hash instead, my %stuff = ( year => '1999', foo => 'bar', baz => 'quux', ); Now there is no reason to restrict yourself to single arguments. You ought to be able to call your sub for a list of tags, so let's rewrite to loop over @_,

    sub writeBasicTag { for (@_) { $writer->startTag($_); $writer->characters($stuff{$_}); $writer->endTag($_); } 1; }
    Note that there is a closure on %stuff (as well as $writer), so attention must be paid to scoping and initialization.

    Update: ++The Mad Hatter for typo correction.

    After Compline,
    Zaxo

Re: indirectly accessing variable
by The Mad Hatter (Priest) on Jul 11, 2003 at 15:59 UTC
    Update: Guess I'm a little late to the party...two replies already...heh ; )

    Instead of putting the values into seperate variables like that, use a hash. Then you could do:

    sub writeBasicTag { my $tag = $_[0]; $writer->startTag($tag); $writer->characters($value{$tag}); $writer->endTag($tag); }
      Man, that was fast. I was going to take a break on this one now I have to write more code... :-\