I wanted to build an awesome place for people to discuss module specific issues, but I don't have any more time for this, and there are much better places to discuss Perl-related issues. I'd recommend asking your question on Stack Overflow or on Perl Monks.
If you are looking for a Perl tutorial or Perl-related news, I hope these links will serve you well.
Posted on 2012-02-28 11:52:34.462795-08 by b0sque
Passing XML twig element to another subroutine
So, I may be just missing something, I'm new to XML:Twig. I have several handlers defined, and those are all working great. At the end of each handler, I print it's output out as a new line to an existing output file (file handle opened at the beginning of the script). However, in a couple handlers, they each have 3 variables (contents of child elements) that are free-form text, and I need to remove certain characters. I wrote a subroutine that would expect a string variable, modify that variable, and return the modified version back to the subroutine call. If I were to print the variable, like $name in the example below, in the calling code, it prints the text value. But, what I receive in the subroutine is a hash reference to the XML object that contains the string value (like a pointer). Am I passing this wrong somehow? Can I not pass an element to another subroutine? Some example code would be:
$name = $ele->first_child('name')->text; #at this point $name would be "Travis" for example, if I printed it; $name = string_modify($name); print $name; sub string_modify() { my $string = $_; # as soon as I get here, the $string value I received isn't "Travis", it's a hash reference $string =~ s/is/as/gi; return $string; }
Direct Responses: 13656 | Write a response
Posted on 2012-02-29 03:08:40.709007-08 by mirod in response to 13655
Re: Passing XML twig element to another subroutine

It looks like you are also new to Perl ;--)

The arguments to a sub are passed in the @_ array, not in $_.

So your sub should start with

sub string_modify() { my( $string) = @_;

or

sub string_modify() { my $string = shift; # shifts @_ by default

as it is, the content of $_ is still set by XML::Twig to the element that triggered the handler.

Direct Responses: 13660 | Write a response
Posted on 2012-03-05 18:47:55.403982-08 by b0sque in response to 13656
Re: Passing XML twig element to another subroutine
Hey mirod, Good catch. I'm not sure what I was thinking when I wrote the subroutine. I remembered the concept of shift after I posted. I appreciate the response. So, second question, and hopefully it's not stupid (like the above, lol). Using this module, I understand that if I had XML that looked like:
<parent> <name>Anakin</name> <child> <name>Luke</name> <grandchild weapon="lightsaber"> <name>Ben</name> </grandchild> </child> </parent>
If I wanted to get the name of the grandchild element, I'd could, for example, do a new twig and set the twig root to
$twig = new XML::Twig( TwigRoots => { 'parent/child/grandchild' => 1 } ); $twig->parsefile($file); $grandchild = $twig->root; $name = $grandchild->first_child('name')->text; print "\n" . $name . "\n";
But, what do I do if I want to get the weapon ATTRIBUTE?? I understand how to get child elements and their text value, but I don't understand how to get the attributes of an element. I've been reading the cpan documentation. Would something like this work? (code continues from the above)
$weapon = $grandchild->att('weapon')->text;
?? For what it's worth, I've definitely tried the above, and anything else I can think of. I can't figure out for the life of me how to get a specific attribute's text value.
Direct Responses: 13661 | Write a response
Posted on 2012-03-05 22:54:54.154365-08 by mirod in response to 13660
Re: Passing XML twig element to another subroutine

Did you try:

$grandchild->att('weapon')

? There is no need for a method call on the attribute, att already returns its value. To set an attribute, use set_att

$grandchild->set_att( weapon => "pitchfork")

Have you seen the Quick ref card? xmltwig.org/xmltwig/quick_ref.html

Direct Responses: 13739 | Write a response
Posted on 2012-06-20 13:57:37.396489-07 by b0sque in response to 13661
Re: Passing XML twig element to another subroutine
So, sorry it's been about a while, got put on a different project at work. So, I've fixed all the problems in my code, and it works like a charm, except for this same issue. This time, I'll explain what I'm needing, and put in some real XML so it makes sense.
Basically, I'm getting XML report files from a tool. I'm normalizing them for import into a database. The issue is a) the XML tags in the output of the tool suck, and b) some machines have multiple IP addresses....
Below is some example XML: (it's example data; i realize there is no 127.0.0.2)
<ASSET> <ASSET_ID TYPE="Host Name">System A</ASSET_ID> <ASSET_ID TYPE="IP Address">127.0.0.1</ASSET_ID> <ASSET_ID TYPE="IP Address">127.0.0.2</ASSET_ID> <ASSET_ID TYPE="MAC Address">00:00:00:00:00:00</ASSET_ID> <test> <value>blah</value> </test> <test> <value>blah</value> </test> </ASSET>

That's the part of the XML I'm struggling with. So, how do I query this out? If I set the twig_root like this:
my $roots = { 'ASSET/ASSET_ID' => 1 }; my $twig = new XML::Twig(TwigRoots => $roots); $twig->parsefile($scan_file); my $root = $twig->root;

Now, if it's coded like the above, I can get some of the values, but I can't figure out how to get specific ones. Heck, if I could just loop through the children, and check the attrib value each time and concat it to a variable, that would be awesome. Is there a "next_child" method I don't know about???
Here's what I'm able to do right now:
$hostname = $root->first_child->text; $mac = $root->last_child->text;

so, I can get the first child text value for hostname, and the last_child value and grab the MAC, but I can't figure out how to get at the child with the IP Address... The problem is if I try "first_child_matches", all of them will be the same since they're all <ASSET_ID> tags. I don't know of any "next_child" or "next_child_matches" methods.
Is there a better way to loop through this? If I can get a loop working, it'd be easy to write the if statement to check the attrib and the concat the text value to the correct variable (ie, $ip).
Thoughts anyone?
Direct Responses: Write a response