Xml 不是散列引用

Xml 不是散列引用,xml,perl,Xml,Perl,我在代码第70行的Perl 5.30.x中遇到“nota HASH reference”错误,我试图测试$xml的类型,因此: 我不知道如何解决这个问题,因为我已经离开Perl一段时间了,如果有任何建议,我将不胜感激 代码如下(我希望如此!) #/usr/bin/perl 严格使用; 使用URI; 使用LWP::Simple; 使用Net::Amazon; 使用XML::Simple; 使用常量AMAZON_TOKEN=>“AMAZON TOKEN deleted”; 使用常量DEBUG=>0;

我在代码第70行的Perl 5.30.x中遇到“nota HASH reference”错误,我试图测试$xml的类型,因此:

我不知道如何解决这个问题,因为我已经离开Perl一段时间了,如果有任何建议,我将不胜感激

代码如下(我希望如此!)

#/usr/bin/perl
严格使用;
使用URI;
使用LWP::Simple;
使用Net::Amazon;
使用XML::Simple;
使用常量AMAZON_TOKEN=>“AMAZON TOKEN deleted”;
使用常量DEBUG=>0;
#了解我们的论点。第一个论点是
#要获取的URL,第二个是输出。
我的$url=shift | | die“$0[]\n”;
my$output=shift | |'/www/htdocs/cloud.html';
#我们需要在某个时候获取Alexa XML
#我们将做几次不同的操作,因此我们创建一个
#它的子例程。使用URI模块,我们可以
#使用查询正确编码URL。事实上,你会
#请注意,此函数的大部分与
#最后,我们使用LWP::Simple to Actual
#下载并返回XML。
#####################################################
子xml{
我的$url=shift;
$url=“http://$url”除非$url=~m[^http://];
如果调试,则警告“正在为$url获取Alexa数据\n”;
我的@args=(
cli=>10,dat=>snba,
版本=>'7.0',url=>$url,
);
我的$basehttp://data.alexa.com/data';
my$uri=uri->new($base);
$uri->查询表单(@args);
$uri=$uri->as_字符串;
返回get($uri);
}
#然而,原始XML对我们没有好处,因为我们想要提取
#特别感兴趣的项目。我们使用XML::Simple to turn
#将XML转换为Perl数据结构,因为这样更容易
#而不是摆弄事件处理(如XML::Parser)
#或者XML::SAX),我们知道只有少量
#数据。我们想要相关网站的列表和
#相关产品。我们提取并返回两者。
#####################################################
子句柄{
我的$page=shift;
我的$xml=XMLin($page);
我的@related=地图{
{
asin=>$\uU->{asin},
title=>$\uU->{title},
href=>$xml->{RLS}{PREFIX}.$\->{href},
}
}@{$xml->{RLS}{RL};
我的@产品;
if(ref$xml->{SD}{AMZN}{PRODUCT}eq'ARRAY'){
@products=map{$\->{ASIN}}{$xml->{SD}{AMZN}{PRODUCT}};
}else{@products=$xml->{SD}{AMZN}{PRODUCT}{ASIN};}
退货(\@相关,\@产品);
}
#完成的功能;现在我们来看看这个节目:
如果调试失败,则警告“开始URL为$URL\n”;
我的@products;#产品ASIN的运行积累
{
my$page=fetch_xml($url);
my($related,$new_products)=处理xml($page);
@产品=@$新产品;#运行列表
对于(@$相关){
my$xml=fetch_xml($\->{href});
my($related,$new_products)=处理xml($page);
推出@产品,@$新产品;
}
}
#我们现在在@products中有一个产品列表,所以
#我们最好对他们做点什么。让我们看看
#把他们放在亚马逊上,看看他们的标题是什么。
我的$amazon=Net::amazon->new(令牌=>amazon\u令牌);
我的%products=map{$\=>undef}@products;
对于我的$asin(分类键%products){
如果调试,则警告“搜索$asin…\n”;
my$response=$amazon->search(asin=>asin);
my@products=$response->properties;
除非@products==1,否则“ASIN不是唯一的!?”;
我的$product=$products[0];
$products{$asin}={
名称=>$product->ProductName,
价格=>$product->OurPrice,
asin=>asin美元,
};
}
#对。我们现在有了名称、价格和价格
#阿辛。让我们输出一个HTML报告:
{
乌马斯克022;
如果调试,则警告“写入$output\n”;
打开我的$fh,“>”,$output或die$!;
打印$fh“围绕$url的云”;
if(键%products){
打印$fh”“;
对于我的$asin(分类键%products){
my$data=$products{$asin};
printf$fh”“。
“%s”,
@{$data}{qw(asin名称价格)};
}
打印$fh”“;
}
else{print$fh“未找到相关产品。\n”;}
打印$fh“\n”;
}
您正在使用的。这是一个错误。即使是模块的文档也与我一致:

此模块的状态

此模块在新代码中的使用非常重要 气馁。其他模块提供更多功能 直接一致的接口。特别地, 强烈推荐,您可以参考 为教程介绍

是另一个很好的选择

此模块的主要问题是选项太多 (其中一些有不幸的违约)以及 这些选项相互作用-通常会产生意想不到的结果

带有bug修复和文档修复的补丁是受欢迎的,但是是新的 不太可能添加功能

如果没有看到您的XML,很难确定,但我认为这就是发生的情况。Simple以其返回的数据结构不一致而闻名。输入文档中的一个小更改可能会对返回的数据结构产生重大影响。在一个非常相似的文档上,将哈希引用转换为数组引用是非常常见的


我的建议是停止使用XML::Simple。就我个人而言,我会用XML::LibXML替换它。

你能把代码包括进来,这样我们就可以看到可能失败的地方吗?检查
ref($XML)
看看它使用的是什么类型的引用吗?一些未指定的代码希望引用散列(可能还有其他东西),但它得到的是它不期望的其他东西。如果没有更多,我们将无法为您提供更多帮助;“XML:HASH(0x3ba8fa8)”
#!/usr/bin/perl
use strict;
use URI;
use LWP::Simple;
use Net::Amazon;
use XML::Simple;
use constant AMAZON_TOKEN => 'amazon token deleted';
use constant DEBUG => 0;

# get our arguments. the first argument is the
# URL to fetch, and the second is the output.
my $url = shift || die "$0 <url> [<output>]\n";
my $output = shift || '/www/htdocs/cloud.html';

# we'll need to fetch the Alexa XML at some point, and
# we'll do it a few different times, so we create a 
# subroutine for it. Using the URI module, we can
# correctly encode a URL with a query. In fact, you'll
# notice the majority of this function is involved with
# this, and at the end we use LWP::Simple to actually
# download and return the XML.
#####################################################
sub fetch_xml {
    my $url = shift;
    $url = "http://$url" unless $url =~ m[^http://];
    warn "Fetching Alexa data for $url\n" if DEBUG;

    my @args = (
        cli => 10,     dat => 'snba',
        ver => '7.0',  url => $url,
    );

    my $base = 'http://data.alexa.com/data';
    my $uri = URI->new( $base );
    $uri->query_form( @args );
    $uri = $uri->as_string;

    return get( $uri );
}

# raw XML is no good for us, though, as we want to extract
# particular items of interest. we use XML::Simple to turn
# the XML into Perl data structures, because it's easier
# than fiddling with event handling (as with XML::Parser
# or XML::SAX), and we know there's only a small amount of
# data. we want the list of related sites and the list of
# related products. we extract and return both.
#####################################################
sub handle_xml {
    my $page = shift;
    my $xml = XMLin( $page );
    my @related = map {
        {
            asin => $_->{ASIN},
            title => $_->{TITLE},
            href => $xml->{RLS}{PREFIX}.$_->{HREF},
        }
    } @{ $xml->{RLS}{RL} };

    my @products;
    if (ref $xml->{SD}{AMZN}{PRODUCT} eq 'ARRAY') {
        @products = map { $_->{ASIN} } @{ $xml->{SD}{AMZN}{PRODUCT} };
    } else { @products = $xml->{SD}{AMZN}{PRODUCT}{ASIN}; }

    return ( \@related, \@products );
}

# Functions done; now for the program:
warn "Start URL is $url\n" if DEBUG;
my @products; # running accumulation of product ASINs

{
    my $page = fetch_xml( $url );
    my ($related, $new_products) = handle_xml( $page );
    @products = @$new_products; # running list

    for (@$related) {
        my $xml = fetch_xml( $_->{href} );
        my ($related, $new_products) = handle_xml( $page );
        push @products, @$new_products;
    }
}

# We now have a list of products in @products, so
# we'd best do something with them. Let's look
# them up on Amazon and see what their titles are.
my $amazon = Net::Amazon->new( token => AMAZON_TOKEN );
my %products = map { $_ => undef } @products;

for my $asin ( sort keys %products ) {
    warn "Searching for $asin...\n" if DEBUG;
    my $response = $amazon->search( asin => $asin );
    my @products = $response->properties;
    die "ASIN is not unique!?" unless @products == 1;
    my $product = $products[0];
    $products{$asin} = {
        name => $product->ProductName,
        price => $product->OurPrice,
        asin => $asin,
    };
}

# Right. We now have name, price, and
# ASIN. Let's output an HTML report:
{
    umask 022;
    warn "Writing to $output\n" if DEBUG;
    open my $fh, '>', $output or die $!;
    print $fh "<html><head><title>Cloud around $url</title></head><body>";
    if (keys %products) {
        print $fh "<table>";
        for my $asin (sort keys %products) {
            my $data = $products{$asin};
            printf $fh "<tr><td>".
                       "<a href=\"http://amazon.com/exec/obidos/ASIN/%s\">".
                       "%s</a></td> <td>%s</td></tr>",
                       @{$data}{qw( asin name price )};
        }
        print $fh "</table>";
    }
    else { print $fh "No related products found.\n"; }
    print $fh "</body></html>\n";
}