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

I have embedded a Perl interpreter in a C program and loaded the following Perl code into it.

package xmlutil; use XML::Simple; #use strict; # I need symbolic dereferencing. my $xmlFile = "./galaxy.xml"; my $config = XMLin($xmlFile); sub get_ival { $parm_str = $_[0]; # reference the parameter directly. Prints Jane's number print "ref1 = ", $config->{jane}->{tel_no}, "\n"; # attempt to use symbolic dereference. Yields nothing! print "ref2 = ", $$parm_str, "\n"; # construct the same symbolic reference locally # just to make sure. Still yields nothing! $parm_str = "\$" . "config->{jane}->{tel_no}, "\n"; print "ref3 = ", $$parm_str, "\n"; }

My intension is to use the XML::Simple interface from the C code to extract data from the XML. I am currently using the following C code to call the Perl subroutine.

void get_ival( int *int_p, char *parm_str_p ) { char cmd_str[255]; STRLEN na; SV *val; dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs( sv_2mortal( newSVpv( parm_str_p, 0 ) ) ); PUTBACK; call_pv( "xmlutil::get_ival", G_DISCARD ); FREETMPS; LEAVE; }

Can anyone shine a light on how I work arround this problem?

Thanks for your help Wise Ones! :)

Phil

Please note that the square brace characters went funny when I submitted this text. They are there in a couple of places and have turned into links(?) :)

Edit ar0n -- replaced pre with code tags

  • Comment on Problem with symbolic deferencing into XML::Simple's internal representation of an XML file.
  • Select or Download Code

Replies are listed 'Best First'.
Re: Problem with symbolic deferencing into XML::Simple's internal representation of an XML file.
by mirod (Canon) on Dec 05, 2001 at 15:59 UTC

    It is difficult to figure out what the problem is without the XML data you are working with, could you post it by any chance?

    In any case the best way to work with XML::Simple is to use Data::Dumper (or Data::Denter) to print the content of $config, to get an idea of where the data is, and if that's not enough, to use the debugger to get it.

    That is if the problem is with how you use XML::Simple, if it is an XS problem I can't really help you here.

    BTW the problem with square brackets is that you should wrap your code in <code> tags, which disables all shortcut and HTML escapes, see Perl Monks approved HTML tags for more information.

      Hi, I've included the XML file, and the Data::Dumper output for this XML. I hope this helps. The issue appears to be one of symbolic dereferencing rather than XS.

      <?xml version="1.0"?> <galaxy> <jane> <street>Long Lane</street> <city>London</city> <tel_num>441513556421</tel_num> </jane> <jon> <street>Short Street</street> <city>Liverpool</city> <tel_num>441512232233</tel_num> </jon> <sara> <street>Apple Avenue</street> <city>Manchester</city> <tel_num>441223423387</tel_num> </sara> </galaxy> $VAR1 = { 'jane' => { 'tel_num' => '441513556421', 'city' => 'London', 'street' => 'Long Lane' }, 'sara' => { 'tel_num' => '441223423387', 'city' => 'Manchester', 'street' => 'Apple Avenue' }, 'jon' => { 'tel_num' => '441512232233', 'city' => 'Liverpool', 'street' => 'Short Street' } };
(tye)Re: Problem with symbolic deferencing into XML::Simple's internal representation of an XML file.
by tye (Sage) on Dec 05, 2001 at 21:18 UTC

    I think you are confused about symbolic references.

    # reference the parameter directly. Prints Jane's number print "ref1 = ", $config->{jane}->{tel_no}, "\n";
    This tells me that $config->{jane}->{tel_no} probably contains some string mostly containing digits and punctuation.
    # construct the same symbolic reference locally # just to make sure. Still yields nothing! $parm_str = "\$" . "config->{jane}->{tel_no}, "\n"; print "ref3 = ", $$parm_str, "\n";
    Well, first I'll assume you really meant:     $parm_str = "\$" . $config->{jane}->{tel_no}; which does not set $parm_str to be a symbolic reference. A symbolic reference is when $parm_str contains the name (and only the name) of a global variable and you write $$parm_str to access the named global variable.

    I don't think you have any global variables named '$(800)4345-6789'. Note that if you had a global variable that you accessed as $foo, then its name would be "foo" and not '$foo' (or even '\\$foo').

    Also, the value $config->{jane}->{tel_no} is almost certainly not stored in any global variable, so symbolic references can't be used to access that data.

    Perhaps you want non-symbolic references (often called "real" references or "hard" references). Then you'd use:     $parm_str = \$config->{jane}->{tel_no}; But I'd need more description about what you are trying to do before I could say whether that would help you or not.

    Also note that you don't set a variable to some special value to make it a symbolic reference. A symbolic reference happens when you dereference something that isn't a hard reference. Intentional (potential) symbolic references are just simple strings that happen to match the name of some global variable. So it isn't until you try to dereference it that strict can tag it as a symbolic reference.

    Or perhaps you meant to do something like:     $parm_str = '$config->{jane}->{tel_no}'; in which case you'd "dereference" that using eval:     print "value = ", eval($parm_str), "\n"; which I wouldn't suggest is a good idea. Perhaps you are trying to do this because you can't figure out how to get to "jane"'s "tel_no" in cases when you don't know how many levels deep you'll need to go. If so, then this has been discussed a couple of times before so let us know and we can point you to those discussions (if you can't locate them yourself).

            - tye (but my friends call me "Tye")
Re: Problem with symbolic deferencing into XML::Simple's internal representation of an XML file.
by Rhose (Priest) on Dec 05, 2001 at 20:58 UTC
    First off, the code I am attaching is not pretty, and there may well be a LOT better way of doing this, but I hope I am at least on the right track.

    Also, I noticed in your code, you referenced tel_no, but the XML file has tel_num... I will assume tel_num is correct. I also noticed the following was probably a typo:

    $parm_str = "\$" . "config->{jane}->{tel_no}, "\n"; $parm_str = '$config->{jane}->{tel_no}';

    as the string "config->{jane}->{tel_no}" was not correctly terminated. Anyway, here is my first pass, please let me know if this helps/does not help. (I whimped out and used recursion. *Smiles*)

    package xmlutil; #-- Use modules use strict; use XML::Simple; #-- Define constants use constant DEBUG => 1; use constant DELIM => ','; use constant XMLFILE => './galaxy.xml'; #-- Define global variables my $gConfig = XMLin(XMLFILE); #-- This is the sub which is used to interface to the #-- main perl code. Had to do this as the C program does not #-- know $gConfig sub get_ival { #-- Get parameter my $pParm=shift; #-- Return the value print get_ivnode(\$gConfig,$pParm); } #-- This is the sub which recursively processes the XML hash array sub get_ivnode { #-- Get parameters my $pPtr=shift; my @pParm = split(DELIM,shift); #-- Define local variables my $lKey; my $lNewPtr; #-- Get the next key $lKey=shift(@pParm); #-- Display debugging information print '[',$lKey,']',"\n" if DEBUG; #-- Return the value if there are no further keys return $$pPtr unless $lKey; #-- Build the new pointer $lNewPtr=$$pPtr->{$lKey}; #-- Call with next node return get_ivnode(\$lNewPtr,join(DELIM,@pParm)); }
    The code I used to test was:

    use strict; use lib '/temp'; use xmlutil; xmlutil::get_ival('jane,tel_num');

    Notice this "solution" requires you to change how you are calling the perl code -- instead of building the "perlish" string, you list the hierarchy separated by commas.

    Am I off base here, or is this what you wanted?

    Update:

    Might want to change the following line so the recursive sub is called one time fewer.

    return $$pPtr unless $lKey; return $$pPtr->{$lKey} unless $pParm[0];
      Thanks for your help... this is great. Sorry 'bout the typos you pointed out. I typed the code in because my cut'n'paste has packed in. Thanks again, I will try your solution immediately. Phil