in reply to Re^6: Update XML Values using two primary keys
in thread Update XML Values using two primary keys

my($lat_key, $lon_key) = split(/./, $, 2);

The first argument to split is a regular expression in which the dot is a metacharacter and should be escaped. Note that since both lat and lon also contain a dot perhaps some other separator character would be a better choice if you want to split the keys. A comma would do and would not need to be escaped.

but I am getting error

You've chosen not to share the precise text of the error message. I cannot imagine why.


🦛

Replies are listed 'Best First'.
Re^8: Update XML Values using two primary keys
by pratikpooja (Novice) on Jan 12, 2021 at 17:43 UTC

    Sorry, It was my mistake, I pasted the wrong code. The correct code is below. I am trying to add new nodes in the XML with the rejected HoH keys but during building, I am getting an error of "bad name at /usr/local/lib/x86_64-linux-gnu/perl/5.30.0/XML/LibXML.pm".

    When I am splitting the key to lat long, it gets split with the number, not the decimal part.

    In the else part, how can I get the rejected HoH keys?

    Thank you.
    my $dom = 'XML::LibXML'->load_xml(location => 'test.osm'); for my $node ($dom->findnodes('/osm/node')) { my $tag = $node->findnodes('tag[@k="name"]')->[0]; my $key = "$node->{lat}.$node->{lon}"; if (exists $HoH{$key}){ $tag->{v} = $HoH{$key}->{name}; $node->{id} = $HoH{$key}->{id}; } else { foreach my $key (keys %HoH) { #print $key,"\n"; my ($lat_key,$lon_key) = (split /[.]/, $key)[0,2]; my $new_node = 'XML::LibXML::Element'->new("node"); my $id = 'XML::LibXML::Attr'->new("id",$HoH{$key}->{id}); my $lat = 'XML::LibXML::Attr'->new("lat",$lat_key); my $lon = 'XML::LibXML::Attr'->new("lon",$lon_key); $new_node->setAttribute($id); $new_node->setAttribute($lat); $new_node->setAttribute($lon); my $new_node_child = 'XML::LibXML::Element'->new("tag"); my $k = 'XML::LibXML::Attr'->new("k",'name'); my $v = 'XML::LibXML::Attr'->new("v",$HoH{$key}->{name}); $new_node_child->setAttribute($k); $new_node_child->setAttribute($v); $new_node->addChild($new_node_child); } } } $dom->toFile('new_test.osm');
      When I am splitting the key to lat long, it gets split with the number, not the decimal part.

      I'm not the best one to help with XML stuff, but I can perhaps offer help on this. I think the best approach is not to split away what you do not want, but to extract what you do want, real numbers in this case. The Regexp::Common module is useful in this, for it defines a real-number pattern.

      Win8 Strawberry 5.30.3.1 (64) Tue 01/12/2021 14:15:24 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings # pm#11126809 use Regexp::Common qw(number); my $rx_lat_lon = qr{ (?<! \d) $RE{num}{real} (?! \d) }xms; for my $lat_lon ( '123,456', '12.345, -0', ' -2. , 0.987', ' -.0 ,0.987 ', '0, -0', '.0 ,-.0', '0. , -0.', ' 0.0 , -0.0 ', '1, -1', '.1 ,-.1', '1. , -1.', ' 1.2 , -1.2 ', '123 456', '123', 'foo', '123,foo', 'foo,123', '1.234.5', ) { my $got_lat_lon = my ($lat, $lon) = $lat_lon =~ m{ \A \s* ($rx_lat_lon) \s* , \s* ($rx_lat_lon) \s* \z + }xms; # $lat_lon =~ m{ $rx_lat_lon }xmsg; # no data validation if ($got_lat_lon) { printf "%18s -> lat %-10s lon %-10s \n", "'$lat_lon'", n_or_undef($lat), n_or_undef($lon); } else { print "'$lat_lon' FAILED to extract lat/lon \n"; } } sub n_or_undef { return defined $_[0] ? "'$_[0]'" : 'undef'; } ^Z '123,456' -> lat '123' lon '456' '12.345, -0' -> lat '12.345' lon '-0' ' -2. , 0.987' -> lat '-2.' lon '0.987' ' -.0 ,0.987 ' -> lat '-.0' lon '0.987' '0, -0' -> lat '0' lon '-0' '.0 ,-.0' -> lat '.0' lon '-.0' '0. , -0.' -> lat '0.' lon '-0.' ' 0.0 , -0.0 ' -> lat '0.0' lon '-0.0' '1, -1' -> lat '1' lon '-1' '.1 ,-.1' -> lat '.1' lon '-.1' '1. , -1.' -> lat '1.' lon '-1.' ' 1.2 , -1.2 ' -> lat '1.2' lon '-1.2' '123 456' FAILED to extract lat/lon '123' FAILED to extract lat/lon 'foo' FAILED to extract lat/lon '123,foo' FAILED to extract lat/lon 'foo,123' FAILED to extract lat/lon '1.234.5' FAILED to extract lat/lon
      (I haven't tested it, but I think this code will work under virtually any Perl version. (Update: Counter-examples are welcome!))

      Some comments:

      • The $RE{num}{real} pattern is not bounded (by design!), so defining an explicit $rx_lat_lon bounded pattern with
            my $rx_lat_lon = qr{ (?<! \d) $RE{num}{real} (?! \d) }xms;
        is IMHO good practice and gives you a single point at which to change the definition of a lat/lon value should this become necessary.
      • Defining an explicit pattern for matching a lat/lon field with
            m{ \A \s* ($rx_lat_lon) \s* , \s* ($rx_lat_lon) \s* \z }xms
        is again good practice IMHO because it can provide for a high degree of data validation. The $got_lat_lon flag is true if valid data is extracted.
      • If you are certain there will always be exactly two lat/lon sub-fields present and you don't care what else is there, you can use the simpler
            m{ $rx_lat_lon }xmsg
        matching expression (note the /g modifier). The $got_lat_lon flag becomes almost meaningless in this case.


      Give a man a fish:  <%-{-{-{-<

        Thank you. Actually, my Hash Key is a combination of lat lon value like 53.58464144.8.560693391. I was trying to separate the lat lon value so that I can add new tags to my XML file with the lat and on value respectively.

        I did the split part of lat and lon by using the split and join module.
        my @lat_lon_key = (split /[.]/, $key); my $lat_key = join('.', @lat_lon_key[0,1]); my $lon_key = join('.', @lat_lon_key[2,3]);
        $VAR1 = { '53.58964145.8.560993391' => { 'name' => 'A99_984_KEI', 'id' => '-1643796' }, '53.58464146.8.560693392' => { 'id' => -1643795, 'name' => 'A88_984_KEI' } };

        In the above Hash, if the 1st Hash key is present in the XML then it gets updated but if the 2nd Hash key is not present or rejected then it should get added as new tag in XML.

        Now my problem is I am not getting the desired rejected HoH keys in my else part of the statement. What I have to do in else part to get the rejected HoH key and build a new node in XML with it?