http://www.perlmonks.org?node_id=990475

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

As I have posted before, I have to maintain a script written XML::Twig to validate dictionary entries. In one part of the entry we can have <la> elements which are used to hold label information such as whether the word is rare or not. The test for rare is that the la element contains the text "rare".

I have now been asked to modify this so that the word is not treated as rare when the la element is marked with an attribute fq with a vlaue of 0 or 1. The fq attribute can also have a value of 2 in which case the word is still to be treated as rare.

My code so far looks like this:

sub is_la_rare { my $elt = shift; # can be <labels> or <def> foreach my $label ($elt->children('la') ) { next unless $label->text eq "rare"; my $isNowRare = 0; if ( ($label->att('fq') eq "0") || ($label->att('fq') eq "1") ) { $isNowRare = 1; } if ( !$isNowRare ) { return 1; } } return 0; }

The problem is that this generates "Use of uninitialized value in string eq" which I think is caused by the cases when the la element does not have an fq attribute on it. So I want to add a test for the attribute like this: ($label ->att('fq') && $label->att('fq') == "1"). The first bit returns the value of the attribute so it works when that is 1 but if I try to use where the attribute is "0" ($label ->att('fq') && $label->att('fq') == "0") it doesn't work because it then returns 0 for the first bit.

Is there a way of testing for the presence of an attribute in XML::Twig which would return "1" if the attribute is present regardless of the value of the attribute?

Replies are listed 'Best First'.
Re: XML::Twig - how can I test for an attribute when the attribute value is 0?
by philiprbrenan (Monk) on Aug 29, 2012 at 14:14 UTC

    Please assign:

    my $f = $label ->att('fq');

    and then test whether $f is defined before attempting to decode its actual value.

      I've actually been able to test if it is defined in one step which enabled me to keep the original code structure:if (defined $elt->att('fq') && $la->att('fq') eq '0') does what I need.

      just to show that there is indeed "more than one way to do it" in Perl, I have spotted in another piece of code written usingXML::Twig one of my colleagues used the start tag function and looked for the string "fq=" which would also work but is not as elegant as using defined in my opinion.

Re: XML::Twig - how can I test for an attribute when the attribute value is 0?
by kcott (Archbishop) on Aug 30, 2012 at 00:38 UTC

    I'm not an XML::Twig user; however, its documentation has:

    atts
    Return a hash ref containing the element attributes

    So, you should be able to determine if fq is present with exists:

    exists $label->atts()->{fq}

    This will return true even if the value is undef.

    Assuming the attribute exists, you may also want to check the value with defined and possibly even length (to check for a zero-length string) before checking for truth or specific values.

    -- Ken

Re: XML::Twig - how can I test for an attribute when the attribute value is 0?
by Jenda (Abbot) on Aug 30, 2012 at 12:48 UTC
    no warnings 'uninitialized';

    Don't bend backwards just to silence a warning that's extremely unlikely to ever be of any use.

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

Re: XML::Twig - how can I test for an attribute when the attribute value is 0?
by Khen1950fx (Canon) on Aug 30, 2012 at 02:21 UTC
    mirod did a post showing how to handle attributes. Re: retrieving attribute text with xml::twig. Here's his example:
    #!/usr/bin/perl -l BEGIN { $| = 1; $^W = 1; } use strict; use autodie; use warnings; use XML::Twig; my $elt =XML::Twig->new( start_tag_handlers => { _all_ => sub { print join( ' - ' => values %{ $_->atts } ); } })->parse( \*DATA ); __DATA__ <doc> <elt att="not rare">fq0</elt> <elt att="not rare">fq1</elt> <elt att="rare">fq2</elt> </doc>

      Once again you did not read/understand the question being asked, which philiprbrenan and kcott already answered

        Did you read mirod's post?