Reputation: 25
For my problem I am having a user enter a string to search for a provider, then the provider as well as some select plan information appears in the console. However, I cannot find out how to print out a select provider + the other information needed all in one.
For example:
Vodafone || 12 months || 120gb
Vodafone || 24 months || 200gb
I have made a start and do not mind too much about the sting input as I can figure that out later, but I cannot find how to firstly search for a select provider and then to print the information. Every provider and all the information is within a < plan > node (see XML below).
XML FILE
<plans>
<internet>
<plan>
<technology>ADSL2+</technology>
<length>12</length>
<provider>Vodafone</provider>
<price>60</price>
<mincost>600</mincost>
<data>120</data>
<shaping>128</shaping>
<homebundle>true</homebundle>
</plan>
<plan>
<technology>ADSL2+</technology>
<length>12</length>
<provider>Telstra</provider>
<price>80</price>
<mincost>800</mincost>
<data>200</data>
<shaping>256</shaping>
<homebundle>true</homebundle>
</plan>
(etc.)
And the current Perl file
use XML::DOM;
my $dom_obj;
my $xml_file= shift;
my $parser = new XML::DOM::Parser;
die "Unable to parse XML document\n" unless $dom_obj = $parser->parsefile($xml_file);
my @nodes = $dom_obj->getElementsByTagName("plan"); #return list of objects of 'Plan'
foreach $elem (@nodes) #for each 'Plan' object
{
foreach $child ($elem->getChildElements) #should return each element under plan?
{
print $child->getNodeValue; #should print elements
print " ";
}
print "\n";
}
I tried an if-statement thinking I was close but only received errors.
foreach $elem (@nodes)
{
if($elem->getElementByTagName("provider")->getFirstChild->getNodeValue =~ /Vodafone/){
print "$unit->getElementByTagName("provider")->getFirstChild->getNodeValue";
print " || ";
print "$unit->getElementByTagName("length")->getFirstChild->getNodeValue";
print " || ";
Any help would be appreciated :)
Upvotes: 1
Views: 148
Reputation: 53498
I'm not familiar with XML::DOM
so would tend to pick up XML::Twig
instead. Something like this:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $provider = 'Vodafone';
sub print_plan_summary {
my ( $twig, $plan ) = @_;
return unless $plan -> first_child_text('provider') eq $provider;
print join ( "||", $plan -> first_child_text('provider'),
$plan -> first_child_text('length')." months",
$plan -> first_child_text('data'). " GB" );
}
my $twig = XML::Twig -> new ( twig_handlers => { 'plan' => \&print_plan_summary } ) -> parsefile('yourXML.xml');
XML::Twig
allows you to set handlers, which take subsets of the xml (in this case plan
elements) and process them individually. Because we can do this, we can manipulate as we go, or just 'simply' extract data from them.
Upvotes: 2
Reputation: 54373
If you can use something else, it's pretty easy with XML::Simple. Usually I don't like XML::Simple, but with this kind of straight-forward XML structure it actually works.
Just read the file (I put it in the __DATA__
section) into a data strucutre, and then iterate over the plans. Those are in an arrayref. Now all you need to do is join the hashref values.
use strict;
use warnings;
use feature 'say';
use XML::Simple;
my $xs = XML::Simple->new;
my $data = $xs->XMLin( \*DATA );
foreach my $plan ( @{ $data->{internet}->{plan} } ) {
next if $plan->{provider} ne 'Vodafone';
say join q{ || }, $plan->{provider}, $plan->{length} . ' months', $plan->{data} . 'gb';
}
Upvotes: 1