#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    14
    Rep Power
    0

    Parsing multiple XML and Store the values into hashmap as Key/Value Pair


    Hi Perl team,

    I am trying to Parse multiple XML and Store the values into hashmap as Key/Value Pair.
    I have tried to Parse multiple XML and Store the values into array as my certain fields has duplicate values so I want the unique value of it and store its corresponding values.

    Does anyone can suggest me ideas?
    I am unable to initiate it as I don't know how to store key/value pair in Hashmap.
    and sample of the XML is

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Configuration for the aero product -->
    <product name="aero" xsi:noNamespaceSchemaLocation="product.xsd" xmlns:xsi="">
    <productName>Airtime</productName>
    <licenseName>Airtime_Tool</licenseName>
    <externalProductIdentifier>10</externalProductIdentifier>
    <baseCode>AT</baseCode>
    <released>true</released>
    <releasePlatforms>
    <platform>all</platform>
    </releasePlatforms>
    <dependsOn>
    <componentDep name="air"></componentDep>
    <componentDep name="air"></componentDep>
    <componentDep name="air"></componentDep>
    </dependsOn>
    <requiredProducts>
    <productDep name="air"></productDep>
    </requiredProducts>
    <releaseTypeAndDelivery>
    <releaseTD releaseType="PVersion" releaseDelivery="DVD"/>
    <releaseTD releaseType="PVersion" releaseDelivery="Web"/>
    <releaseTD releaseType="SVersion" releaseDelivery="Web"/>
    </releaseTypeAndDelivery>
    </product>


    and I only need
    <productName>Airtime</productName>
    <licenseName>Airtime_Tool</licenseName>
    <externalProductIdentifier>10</externalProductIdentifier>
    <baseCode>AT</baseCode>
    <product name =aero>

    and I want to make licenseName as key and rest as a Values of it.

    Thanks!!!
  2. #2
  3. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,221
    Rep Power
    1809
    Code:
    #!/usr/bin/perl
    use strict;
    use warnings;
    
    use Data::Dumper;
    use XML::Simple;
    
    my $ref = XMLin('product.xml');
    #print Dumper $ref;
    
    print
    	"productName: $ref->{productName}\n",
    	"licenseName: $ref->{licenseName}\n",
    	"externalProductIdentifier: $ref->{externalProductIdentifier}\n",
    	"baseCode: $ref->{baseCode}\n",
    	"name: $ref->{name}\n";
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    14
    Rep Power
    0
    Dear keath,

    Thanks for the reply and this is i am printing the values but how i am making sure that which is key and which are corresponding values of it.

    And while parsing XML's if i got a new key which was already present how i will amend any of its existing values of the existing key?
  6. #4
  7. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,221
    Rep Power
    1809
    Do you mean something like this:

    Code:
    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    use Data::Dumper;
    use XML::Simple;
    
    my %xml_data;
    
    my $ref = XMLin('product.xml');
    #print Dumper $ref;
    
    if (exists $xml_data{licenseName}) {
    	# update with new information
    	$xml_data{licenseName} = {
    		name => $ref->{name},
    		basecode => $ref->{baseCode},
    		productName => $ref->{productName},
    		externalProductIdentifier => $ref->{externalProductIdentifier}
    	};
    } else {
    	# new entry
    	$xml_data{$ref->{licenseName}} = {
    		name => $ref->{name},
    		basecode => $ref->{baseCode},
    		productName => $ref->{productName},
    		externalProductIdentifier => $ref->{externalProductIdentifier}
    	};
    };
    
    print Dumper \%xml_data;
    In this example, there is no need for the if/else clause. Both blocks do the same thing, and perl will happily just replace an existing key with new data without requiring a test for existence. This gives you a chance to do something different though.

    If you have some other requirements please give an example of what you want to happen.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    14
    Rep Power
    0
    Product1.xml
    <code>
    <productName>Airtime</productName>
    <licenseName>Airtime_Tool</licenseName>
    <externalProductIdentifier>10</externalProductIdentifier>
    <baseCode>AT</baseCode>
    <product name =aero>
    </code>

    Product2.xml
    <code>
    <productName>Airtime1</productName>
    <licenseName>Airtime_Tool</licenseName>
    <externalProductIdentifier>10</externalProductIdentifier>
    <baseCode>AT</baseCode>
    <product name =aero1>
    </code>

    Keath lets say if my product1 and product2 has same licensename and if I want to amend the existing entry of licensename as shown in the example below :

    Airtime_Tool {"aero;aero1","AT","Airtime1;Airtime",10}

    Thanks!!!
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    14
    Rep Power
    0
    Originally Posted by keath
    Do you mean something like this:

    Code:
    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    use Data::Dumper;
    use XML::Simple;
    
    my %xml_data;
    
    my $ref = XMLin('product.xml');
    #print Dumper $ref;
    
    if (exists $xml_data{licenseName}) {
    	# update with new information
    	$xml_data{licenseName} = {
    		name => $ref->{name},
    		basecode => $ref->{baseCode},
    		productName => $ref->{productName},
    		externalProductIdentifier => $ref->{externalProductIdentifier}
    	};
    } else {
    	# new entry
    	$xml_data{$ref->{licenseName}} = {
    		name => $ref->{name},
    		basecode => $ref->{baseCode},
    		productName => $ref->{productName},
    		externalProductIdentifier => $ref->{externalProductIdentifier}
    	};
    };
    
    print Dumper \%xml_data;
    In this example, there is no need for the if/else clause. Both blocks do the same thing, and perl will happily just replace an existing key with new data without requiring a test for existence. This gives you a chance to do something different though.

    If you have some other requirements please give an example of what you want to happen.
    Also I think the above logic is creating the duplicate entry into Hash when the License Name is same.does it mean that it is not taking LicenseName as a key?
  12. #7
  13. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,221
    Rep Power
    1809
    Originally Posted by vaibhav.shukla
    Also I think the above logic is creating the duplicate entry into Hash when the License Name is same.does it mean that it is not taking LicenseName as a key?
    No, it's not.

    Code:
    $xml_data{$ref->{licenseName}} =
    That's an assignment. There will be only one value under the licenseName key. If you want to store more things, you will need to put an array under that key and push different values to it.

    You only need this much for your described problem:

    Code:
    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    use Data::Dumper;
    use XML::Simple;
    
    my %xml_data;
    
    my $ref = XMLin('product.xml');
    #print Dumper $ref;
    
    $xml_data{licenseName} = {
    	name => $ref->{name},
    	basecode => $ref->{baseCode},
    	productName => $ref->{productName},
    	externalProductIdentifier => $ref->{externalProductIdentifier}
    };
    
    print Dumper \%xml_data;
    There is no need to even test. The most recent data with that key will be the one persisting. Any previous entries will be overwritten. Test it and see.

    If you want to choose based on other data inside the xml file, then you need to test with an if statement and examine what you have.
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    14
    Rep Power
    0
    Hi Keath,

    I am doing this for the above requirement


    if( exists($xml_data{$ref->{licenseName}})) {
    my $current = \$xml_data->{name};
    $xml_data{$ref->{licenseName}} = {
    enumName => $enumName,
    basecode => $ref->{baseCode},
    productName => $ref->{productName},
    externalProductIdentifier => $ref->{externalProductIdentifier},
    name => $$current . " " . $filebasename,
    };
    }
    else {
    $xml_data{$ref->{licenseName}} = {
    name => $ref->{name},
    enumName => $enumName,
    basecode => $ref->{baseCode},
    productName => $ref->{productName},
    externalProductIdentifier => $ref->{externalProductIdentifier}
    };
    }


    but unable to concatenate the name after getting the same LicenseName.
  16. #9
  17. !~ /m$/
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    May 2004
    Location
    Reno, NV
    Posts
    4,221
    Rep Power
    1809
    I'm not sure exactly what you are going for. I don't see $filebasename or $enumName mentioned in the xml file. Not sure where they are coming from.

    Here's an example of updating; maybe it will help.

    I have two xml files:
    product.xml
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <!-- Configuration for the aero product -->
    <product name="aero" xsi:noNamespaceSchemaLocation="product.xsd" xmlns:xsi="">
      <productName>Airtime</productName>
      <licenseName>Airtime_Tool</licenseName>
      <externalProductIdentifier>10</externalProductIdentifier>
      <baseCode>AT</baseCode>
      <released>true</released>
      <releasePlatforms>
        <platform>all</platform>
      </releasePlatforms>
      <dependsOn>
        <componentDep name="air"></componentDep>
        <componentDep name="air"></componentDep>
        <componentDep name="air"></componentDep>
      </dependsOn>
      <requiredProducts>
        <productDep name="air"></productDep>
      </requiredProducts>
      <releaseTypeAndDelivery>
        <releaseTD releaseType="PVersion" releaseDelivery="DVD" />
        <releaseTD releaseType="PVersion" releaseDelivery="Web" />
        <releaseTD releaseType="SVersion" releaseDelivery="Web" />
      </releaseTypeAndDelivery>
    </product>
    product2.xml
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <!-- Configuration for the aero product -->
    <product name="groundo" xsi:noNamespaceSchemaLocation="product.xsd" xmlns:xsi="">
      <productName>Airtime</productName>
      <licenseName>Airtime_Tool</licenseName>
      <externalProductIdentifier>10</externalProductIdentifier>
      <baseCode>AT</baseCode>
      <released>true</released>
      <releasePlatforms>
        <platform>all</platform>
      </releasePlatforms>
      <dependsOn>
        <componentDep name="air"></componentDep>
        <componentDep name="air"></componentDep>
        <componentDep name="air"></componentDep>
      </dependsOn>
      <requiredProducts>
        <productDep name="air"></productDep>
      </requiredProducts>
      <releaseTypeAndDelivery>
        <releaseTD releaseType="PVersion" releaseDelivery="DVD" />
        <releaseTD releaseType="PVersion" releaseDelivery="Web" />
        <releaseTD releaseType="SVersion" releaseDelivery="Web" />
      </releaseTypeAndDelivery>
    </product>
    I can add the names like this:
    Code:
    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    use Data::Dumper;
    use XML::Simple;
    
    my %storage;
    my $file1 = 'product.xml';
    my $file2 = 'product2.xml';
    
    
    my $xmlref = XMLin($file1);
    #print Dumper $ref;
    store_data($xmlref, \%storage);
    
    #=== Read another file
    
    my $xmlref2 = XMLin($file2);
    #print Dumper $ref2;
    store_data($xmlref2, \%storage);
    
    print Dumper \%storage;
    exit;
    
    sub store_data {
    	my ($xml, $store) = @_;
    	
    	if (exists $store->{$xml->{licenseName}}) {
    		# update with new information
    		my $ref = $store->{$xml->{licenseName}};
      		$ref->{name} .= " $xml->{name}";
    	} else {
    		# new entry
    		$store->{$xml->{licenseName}} = {
    			name => $xml->{name},
    			basecode => $xml->{baseCode},
    			productName => $xml->{productName},
    			externalProductIdentifier => $xml->{externalProductIdentifier}
    		};
    	}
    }
    result
    Code:
    $VAR1 = {
              'Airtime_Tool' => {
                                'productName' => 'Airtime',
                                'basecode' => 'AT',
                                'externalProductIdentifier' => '10',
                                'name' => 'aero groundo'
                              }
            };
    But that's not the only option. It might be better to combine results in an array:
    Code:
    sub store_data {
    	my ($xml, $store) = @_;
    	
    	if (exists $store->{$xml->{licenseName}}) {
    		# update with new information
    		my $ref = $store->{$xml->{licenseName}};
    		if (ref $ref->{name} eq 'ARRAY') {
    			# There are already at least two names stored
      			push @{$ref->{name}}, $xml->{name};
      		} else {
      			# convert the entry to an array with the two entries we have
      			$ref->{name} = [$ref->{name}, $xml->{name}];
      		}
    	} else {
    		# new entry
    		$store->{$xml->{licenseName}} = {
    			name => $xml->{name},
    			basecode => $xml->{baseCode},
    			productName => $xml->{productName},
    			externalProductIdentifier => $xml->{externalProductIdentifier}
    		};
    	}
    }
    result
    Code:
    $VAR1 = {
              'Airtime_Tool' => {
                                'productName' => 'Airtime',
                                'basecode' => 'AT',
                                'name' => [
                                            'aero',
                                            'groundo'
                                          ],
                                'externalProductIdentifier' => '10'
                              }
            };
    Or, as I said in a previous post, you could store the entire results in an array attached to licenseName, so that duplicates are stored in full. You have the power to chose any parts you want, but you have to decide what exactly you want to happen.

    Comments on this post

    • vaibhav.shukla agrees : Thanks !!

IMN logo majestic logo threadwatch logo seochat tools logo