我需要存储xml数据
<pathway name="path:ko00010" org="ko" number="00010"
title="Glycolysis / Gluconeogenesis"
image="http://www.kegg.jp/kegg/pathway/ko/ko00010.png"
link="http://www.kegg.jp/kegg-bin/show_pathway?ko00010">
<entry id="13" name="ko:K01623 ko:K01624 ko:K01622 ko:K11645 ko:K16305 ko:K16306" type="ortholog" reaction="rn:R01070"
link="http://www.kegg.jp/dbget-bin/www_bget?K01623+K01624+K01622+K11645+K16305+K16306">
<graphics name="K01623..." fgcolor="#000000" bgcolor="#BFBFFF"
type="rectangle" x="483" y="404" width="46" height="17"/>
</entry>
</pathway>
进入数据结构以供进一步使用。 DS喜欢哈希和数组, 这是我的代码
#!/usr/bin/perl
use XML::LibXML;
use strict;
use warnings;
my $parser = new XML::LibXML;
my $xmlp= $parser -> parse_file("ko00010.xml");
my $rootel = $xmlp -> getDocumentElement();
my $elname = $rootel -> getName();
my @rootelements=$rootel -> getAttributes();
foreach my $rootatt(@rootelements){
my $name = $rootatt -> getName();
my $value = $rootatt -> getValue();
print " ${name}[$value]\n ";
}
my @kids = $rootel -> childNodes();
foreach my $child(@kids) {
my $elname = $child -> getName();
my @atts = $child -> getAttributes();
foreach my $at (@atts) {
my $name = $at -> getName();
my $value = $at -> getValue();
print " ${name}[$value]\n ";
}
}
到目前为止,我可以访问除Graphics节点及其子节点之外的所有元素
答案 0 :(得分:5)
另一种完全不同的方法:使用XML架构,并使用CPAN模块XML::Compile
进行XML数据的自动转换。与XML::Simple
之类的其他xml到数据工具相比,XML::Compile
不必猜测或用“ForceArray”等选项进行调整,如果子元素有时会变成数组,有时是标量。
如果您的数据没有XML架构,那么您可以使用trang
自动创建一个:
trang testdata.xml schema.xsd
XML::Compile
附带命令行工具xml2yaml
以便快速转换:
xml2yaml testdata.xml schema.xsd > testdata.yaml
答案 1 :(得分:2)
我不清楚您想要准确创建哪种数据结构。或者,当您可以使用XPath获取所需的数据而不必将XML映射到其他内容时,为什么要创建数据结构。
在我看来,你有点想要模仿XML::Simple所做的事情。在这种情况下,不直接使用XML :: Simple?我知道一般不建议使用任何复杂的XML,但是如果你的XML很简单并且XML :: Simple创建的数据适合你,那么使用广泛使用的模块比尝试重写它更安全(我应该知道,我在XML :: Twig中重写了它,它并不特别困难,但也不一定非常简单)。
答案 2 :(得分:1)
你需要做
my @grand_kids = $child -> childNodes();
在你的第二个foreach中,并通过属性再做一步
我为你做了一个例子
#!/usr/bin/perl
use XML::LibXML;
use strict;
use warnings;
my $parser = new XML::LibXML;
my $xmlp= $parser->parse_file("ko00010.xml");
my $rootel = $xmlp->getDocumentElement();
my $elname = $rootel->getName();
my @rootelements=$rootel->getAttributes();
foreach my $rootatt(@rootelements){
printf "R {%s}[%s]\t", $rootatt->getName(), $rootatt->getValue();
}
my @kids = $rootel -> childNodes();
foreach my $child(@kids) {
printf "\nCH = %s\n", $child->getName();
my @atts = $child->getAttributes();
foreach my $at (@atts) {
printf "C {%s}[%s]\t", $at->getName(), $at->getValue();
}
my @grand_kids=$child->childNodes();
foreach my $grand_child(@grand_kids) {
printf "\nGR CH = %s\n", $grand_child->getName();
my @atts2 = $grand_child->getAttributes();
foreach my $at2 (@atts2) {
printf "GC {%s}[%s]\t", $at2->getName(), $at2->getValue();
}
}
}
给出这个输出 - (我不确定#text节点来自哪里)
R {name}[path:ko00010] R {org}[ko] R {number}[00010] R {title}[Glycolysis / Gluconeogenesis] R {image}[http://www.kegg.jp/kegg/pathway/ko/ko00010.png] R {link}[http://www.kegg.jp/kegg-bin/show_pathway?ko00010]
CH = #text
CH = entry
C {id}[13] C {name}[ko:K01623 ko:K01624 ko:K01622 ko:K11645 ko:K16305 ko:K16306] C {type}[ortholog] C {reaction}[rn:R01070] C {link}[http://www.kegg.jp/dbget-bin/www_bget?K01623+K01624+K01622+K11645+K16305+K16306]
GR CH = #text
GR CH = graphics
GC {name}[K01623...] GC {fgcolor}[#000000] GC {bgcolor}[#BFBFFF] GC {type}[rectangle] GC {x}[483] GC {y}[404] GC {width}[46] GC {height}[17]
GR CH = #text
CH = #text
答案 3 :(得分:0)
XML :: Simple可以使用,但也建议使用LibXML。这里有一些perlmonks article关于一些值得注意的差异,并从XML :: Simple转换为LibXML。
使用 XPathContext 和 findnodes 使用LibXML的一种方法:
use strict;
use warnings;
use XML::LibXML;
use Data::Dumper;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file("ko00010.xml");
my $root = $doc->getDocumentElement();
my %nodeHash = ();
# get list of nodes and stores each nodeName(key) and textContent(value) in %nodeHash
my $perlmatch = sub {
die "Not a nodelist"
unless $_[0]->isa('XML::LibXML::NodeList');
die "Missing a regular expression"
unless defined $_[1];
my $i = 0;
while ( my $node = $_[0]->get_node($i++) ) {
push @{ $nodeHash{$node->nodeName} }, $node->textContent;
}
};
# Create XPathContext and find all nodes
my $xc = XML::LibXML::XPathContext->new($root);
$xc->registerFunction( 'perlmatch', $perlmatch ); # register 'perlmatch' function
$xc->findnodes('perlmatch(//*, ".")') or die "Error retrieving nodes."; # //* is to go through all parent and child nodes, "." to match any nodeName
print Dumper(%nodeHash); # print the contents of nodeHash (you can see the final hash structure here)
取自CPAN XML::LibXML::XPath上的示例(替换为哈希而不是数组和&#34;。&#34;用于所有节点)。