in reply to XML::Simple--dealing with a variable element

Chew on this:
@attrs = map { @{ $_->{attributes}{attribute} } } values %{ $data->{dataschemas}{dataschema} };

Update: actually, it doesn't look like your attribute nodes result in an array. Do you need the attribute names too, or just the values?

Maybe this will be clearer:

foreach my $dataschema ( values %{ $data->{dataschemas}{dataschema} } +) { while( my ($name, $value) = each %{ $dataschema->{attributes}{attr +ibute} } ) { # do something with the name and value } }

Replies are listed 'Best First'.
Re^2: XML::Simple--dealing with a variable element
by bw (Novice) on Jul 26, 2006 at 22:57 UTC
    I'll crack the book to decipher your code. I simply need the names.

    My end goal for all of this is to figure out existing attribute names being used, give a user the opportunity to select from that existing list or add new ones, write out a new <dataschema> stanza, and then update the config file where the <dataschemas> stanza came from.
      Are you sure the names are unique for all the varying groups? If so, then
      @attrs = map { keys %{ $_->{attributes}{attribute} } } values %{ $data->{dataschemas}{dataschema} };
      should do the trick. I think. I usually get dizzy with data structures this deep ;)
        Let's say for a given <dataschema> that one of the <attribute> stanza attributes is 'category'. Within that given <dataschema>, all 'category' names are unique. Some of those 'category' names, however, will appear in other <dataschema> stanza's 'category' names.

        Does that make sense? Does that change the code at all? Have I made you so dizzy that you can't get off the floor?
Re^2: XML::Simple--dealing with a variable element
by bw (Novice) on Jul 27, 2006 at 17:13 UTC
    rhesa: the foreach option is almost working!

    The first element within <attribute> is:
      <attributes>
        <attribute category="" parser="CSVParser" />

    which produces the error:
    Argument "" isn't numeric in each at xmlparser.pl line 58.
      Bad index while coercing array into hash at xmlparser.pl line 58.

    when using the code:

    foreach my $dataschema ( values %{ $data->{dataschemas}{dataschema} } +) { while( my ($name, $value) = each %{ $dataschema->{attributes}{attrib +ute} } ){ # do something with the name and value print "\$name is: $name\n\$value is: $value\n"; } }
    When I used keys in place of each, I get the print line to work, but I'm stuck in an infinite loop in the process.

    This shows that I don't understand very well hashes and hash functions with respect to the while( my ($name, $value) = each %{ $dataschema->{attributes}{attribute} } ) line since this error doesn't make sense to me.

    I know that I'm getting hung up on the category="" item, but that's as far as I've gone in my debug process.
      Your newer data shows that you usually have an array of "attribute" nodes, while I was assuming it would be a hash. I'm forcing XML::Simple to always make an array of the "attribute" nodes, and have changed the code to accomodate that.
      use XML::Simple; $data = XMLin( \*DATA, KeepRoot => 1, ForceArray => [ qw/attribute/ ] + ); @attrs = map { $_->{category} } # We want the c +ategory value map { @{ $_->{attributes}{attribute} } } # for each attr +ibute values %{ $data->{dataschemas}{dataschema} }; # in all datasc +hemas. print "@attrs\n"; __DATA__ <dataschemas> <dataschema name="varyingName1"> <attributes> <attribute category="one" fair="no" /> </attributes> </dataschema> <dataschema name="varyingName2"> <attributes> <attribute category="" parser="CSVParser" /> <attribute category="APS" internalCategory="aps" /> <attribute category="ASC" internalCategory="asc" /> <attribute category="ASMT" internalCategory="asmt" /> <attribute category="LE" internalCategory="l&amp;e" /> <attribute category="NCO" internalCategory="nco" /> <attribute category="NEED TITLE" internalCategory="need title" + /> <attribute category="New Need ID" internalCategory="need id" / +> <attribute category="SUMMARY OF DELIVERABLES" parser="TextPars +er" extract="true" segmentation="hard" /> </attributes> </dataschema> </dataschemas>
      A version based on the foreach / while idea:
      foreach my $dataschema ( values %{ $data->{dataschemas}{dataschema} } +) { foreach my $attr ( @{ $dataschema->{attributes}{attribute} } ){ print "category is: ", $attr->{category}, "\n"; } }


        I wrapped the XML snippet with <document> tags and the error went away. Now I can't get anything to print out from within the foreach loop ...

        I tried both versions of this -- foreach and 'map' ones -- and keep getting the following error:

        junk after document element at line 24, column 0, byte 825 at C:/Perl/site/lib/XML/Parser.pm line 168

        where line 24 occurs just above __DATA__. I couldn't figure out from Parser.pm what could be happening. Do you have any suggestions? Thanks much.