(jeffa) Re: XML::Simple
by jeffa (Bishop) on Dec 18, 2002 at 00:56 UTC
|
use Data::Dumper;
my $data = do {local $/;<DATA>};
my $xml = XMLin($data);
print Dumper $xml;
Yields:
$VAR1 = {
'label' => 'gene_of_interest',
'id' => '3'
};
From this we see that label and id are the 'top level'
keys, there is no 'gene' key. However, had the XML been
a bit more proper ...
use strict;
use warnings;
use XML::Simple;
my $data = do {local $/;<DATA>};
my $xml = XMLin($data);
# ... and you use the correct syntax ;)
print $xml->{gene}->{id}, "\n";
print $xml->{gene}->{label}, "\n";
__DATA__
<?xml version="1.0" ?>
<genes>
<gene id = "3" label = "gene_of_interest" />
</genes>
Then all is well. :)
jeffa
L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] [select] |
|
|
What?!?
It is syntactically valid, it just won't do what he wants (no chance in hell).
The expression will evaluate to
$xml->{{}}, and that key (the stringified version of that anonymous hashref) is not defined, so a warning will be thrown.
something like that ;)(actually $xml->{gene}{{}} , but it's not really important)
If you didn't know what the comma operator would do in this expression, read "List" is a Four-Letter Word, as well as perldoc perlop
update:
use Data::Dumper;
local $\="\n";
$a = {
gene => { id => 3, label => 'generrrous' }
};
print $a->{ gene, id}=1;
print $a->{ gene => id };
print Dumper $a;
__END__
1
1
$VAR1 = {
'gene' => {
'label' => 'generrrous',
'id' => 3
},
'gene‡˜id' => 1
};
MJD says you
can't just make shit up and expect the computer to know what you mean, retardo!
** The Third rule of perl club is a statement of fact: pod is sexy.
|
| [reply] [d/l] [select] |
|
|
|
|
Re: XML::Simple
by BrowserUk (Patriarch) on Dec 18, 2002 at 01:25 UTC
|
I started with perl and XML at the same time and I well remember how confusing the syntax of hashes was back then. It gets easier fast. Hopefully the code below will help clarify things.
A few things to note.
You need a root node in your xml. (I used <genes></genes>), this allows you to treat multiple lines as part of a single data structure. The root name will not show up in the Data::Dumper output. You don't use this as part of the structure reference.
You can use a variable/or a hardcoded string in the hash references.
Data::Dumper is very useful for understanding the structure returned by XML::Simple. Don't try it on a very large file of XML because it will churn for ages then run out of memory. Use it on small samples and then comment it out before testing your code on a large file.
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
my $data = do {local $/;<DATA>};
my $xml = XMLin($data);
print Dumper($xml), "\n\n";
for my $id (3,4) {
print $xml->{gene}{$id}{'label'}, "\n";
}
__DATA__
<?xml version="1.0" ?>
<genes>
<gene id = "3" label = "gene_of_interest" />
<gene id = "4" label = "Another_gene_of_interest" />
</genes>
Output C:\test>220720
$VAR1 = {
'gene' => {
'3' => {
'label' => 'gene_of_interest'
},
'4' => {
'label' => 'Another_gene_of_interest'
}
}
};
gene_of_interest
Another_gene_of_interest
C:\test>
Examine what is said, not who speaks. | [reply] [d/l] [select] |
|
|
my $xml = XMLin($data);
I'd recommend this:
my $genes = XMLin($data,
keyattr => { gene => 'id' },
forcearray => [ 'gene' ],
);
My reasoning:
- the return value from XMLin() is a Perl data structure not XML, so $xml is not a very descriptive name
- you are 'folding' the list of gene elements into a hash keyed on the 'id' - it's more readable/maintainable to spell out your requirements rather than relying on the defaults
- any element listed in 'keyattr' should usually also be listed in 'forcearray'
The XML::Simple strict mode node expands on this theme.
Also, you could give XMLin() the DATA globref directly:
XMLin(\*DATA, ...);
| [reply] [d/l] [select] |
|
|
Agreed. I actually had both options on in my first version, but then decided that as the process works without, it might only serve to confuse the OP, and removed them.
Possibly the wrong thing to do in hindsight, but I figured less noise, more clarity?
Same goes for using GLOB's, I still steer clear of them personally, but it would better in production code.
Examine what is said, not who speaks.
| [reply] |
Re: XML::Simple
by sauoq (Abbot) on Dec 18, 2002 at 01:03 UTC
|
The first element in your XML is your XML document. If you want to have more than one "gene" element, you'll have to enclose them in something else.
<?xml version="1.0"?>
<genecollection>
<gene id = "2" label = "gene of some interest" />
<gene id = "3" label = "gene of more interest" />
</genecollection>
Then their IDs would be keys %{$xml->{gene}} and the label of the gene with the id of 2, for example, would be $xml->{gene}{2}{label}... Is that what you are trying to do?
-sauoq
"My two cents aren't worth a dime.";
| [reply] [d/l] [select] |
|
|
Yes, I am trying to do something like that. This is a useful bit of code. Thanks.
| [reply] |
Re: XML::Simple
by pg (Canon) on Dec 18, 2002 at 01:57 UTC
|
Other than what other monks pointed out, I believe a big question mark you had was why the root element, in this case the 'gene', was not in the hash.
The answer is that the default style of XML::Simple is not to keep root element, if you want see the root, do this:
use XML::Simple;
use Data::Dumper;
use strict;
use warnings;
my $data = do {local $/;<DATA>};
my $xml = new XML::Simple(keeproot => 1);# this is what you want
my $tree = $xml->XMLin($data);
print Dumper($tree);
__DATA__
<?xml version="1.0" ?>
<gene id = "3" label = "gene_of_interest" />
| [reply] [d/l] |
Re: XML::Simple
by PodMaster (Abbot) on Dec 18, 2002 at 00:52 UTC
|
Please always express your question in words.
Saying "it doesn't work" isn't very useful.
Always describe what the code is supposed to do (especially when it doesn't do it).
Also, add
use Data::Dumper;
die Dumper $xml;
To your snippet, and hopefully you'll see why it doesn't work (it's cause there is no key in %$xml called gene).
MJD says you
can't just make shit up and expect the computer to know what you mean, retardo!
** The Third rule of perl club is a statement of fact: pod is sexy.
|
| [reply] [d/l] |
|
|
-- PodMaster
I wouldn't say anything but I've seen several replies like this from you recently and I've bitten my tounge enough.
Although I agree that the question was poorly stated, I really think that your tone is offensive and arrogant. Putting your hands on your hips and wagging your finger is no more polite than a poorly asked question and no less a waste to read.
You are free to skip questions which you can't interpret, you can't answer, or which you feel aren't asked skillfully enough.
Hubris might be good in the context of being a programmer but it isn't a desirable personality trait. Some, such as the ever quotable MJD¹, excel at what they do to the degree that they can get away with it. I don't think that you have earned that dubious right.
¹ Although I've gotten a chuckle from Dominus's rants at the clueless too, I do think it is somewhat of a shame he has managed to set such an example. At least he keeps a sense of humor about it though (mostly.)
-sauoq
"My two cents aren't worth a dime.";
| [reply] |
|
|
| [reply] |
|
|
I must also disagree with you, sauoq. Asking for a reasonable explaination of the problem, in words, is not out of the ordinary.
If I recall correctly, in one of my first posts I was also unhelpful in describing the nature of my problem, and fruiture took me to task for it. (That I flamed him afterwards didn't help either, but live and learn...).
Since then, I've been highly verbose in describing my problems, and it's been helpful for everyone: I get my answer sooner, other monks don't have to ask questions or make assumptions, and I get more XP. :-P
I also take exception to your finding PodMaster's tone "arrogant". Are you able to read his mind through the phosphors now? His request seemed very reasonable to me.
I have a coworker in my office/room/whatever, and he's a nice guy, but he drives me mad -- he can't communicate. Good communication makes things happen. Sometimes I have to tell him to speak up, speak clearly, or re-write an email so I can make sense of what he's saying. He doesn't like it, but he'll be a better worker for it.
Maybe his future employers will thank me.
Cheers,
ibanix
$ echo '$0 & $0 &' > foo; chmod a+x foo; foo;
| [reply] [d/l] |
|
|
|
|
A reply falls below the community's threshold of quality. You may see it by logging in.
|