Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql Perl和XPath:数据库表中缺少条目_Mysql_Xml_Perl_Xpath_Mariadb - Fatal编程技术网

Mysql Perl和XPath:数据库表中缺少条目

Mysql Perl和XPath:数据库表中缺少条目,mysql,xml,perl,xpath,mariadb,Mysql,Xml,Perl,Xpath,Mariadb,我想从xml文件中提取数据,并将其导入到MariaDB/MySQL数据库中。xml文件是: Perl代码是: 使用严格; 使用警告; 使用DBI; 使用XML::XPath; 使用XML::XPath::XMLParser; 我的$xp=XML::XPath->new(文件名=>“animals4.XML”); #我的$xp=XML::XPath->new(ioref=>\*数据); my$dbh=DBI->connect(“DBI:mysql:test”、“user”、“pw”{Raise

我想从xml文件中提取数据,并将其导入到MariaDB/MySQL数据库中。xml文件是:


Perl代码是:

使用严格;
使用警告;
使用DBI;
使用XML::XPath;
使用XML::XPath::XMLParser;
我的$xp=XML::XPath->new(文件名=>“animals4.XML”);
#我的$xp=XML::XPath->new(ioref=>\*数据);
my$dbh=DBI->connect(“DBI:mysql:test”、“user”、“pw”{RaiseError=>1,PrintError=>0})
或者死“Fehler beim Verbidungsaufbau zum MariaDB服务器:”。“$DBI::err-<$DBI::errstr\n”;
对于我的$row1($xp->findnodes('//row1s/row1')){
printf“Level---row1\“name\”给出了:%s\n“,$row1->getAttribute(“name”);
对于我的$row2($row1->findnodes('.//row2s/row2')){
printf“Level row2\”type\”给出了:%s\n“,$row2->getAttribute(“type”);
printf“Level row2\”size\”给出了:%s\n“,$row2->getAttribute(“size”);
$dbh->do(
“在animal4(名称、类别、类型、大小)中插入值(?、、?、?)”,
未定义,
$row1->getAttribute(“名称”),
$row1->getAttribute(“类别”),
$row2->getAttribute(“类型”),
$row2->getAttribute(“大小”)
)或死“执行期间出错:”。“$DBI::err->$DBI::errstr(动物$DBI::state)\n”;
}
}
终端输出为:

Level---row1“name”给出:fox
第2级“类型”给出:1
级别行2“大小”给出:10
第2级“类型”给出:2
级别行2“大小”给出:8
级别---第1行“名称”给出:马
第2级“类型”给出:3
级别行2“大小”给出:100
级别---第1行“名称”给出:bee
级别---第1行“名称”给出:黄蜂
这正是我所期望的。但该表包含以下条目:

名称类别类型大小
狐狸哺乳动物110
狐狸哺乳动物28
马类哺乳动物3100
蜜蜂和黄蜂被错过了。有人能帮我解决这个问题吗?我想知道为什么会发生这种情况,因为终端的输出是正常的

谢谢你的帮助

以下是表格的代码:

创建表test01.animal4(
名称VARCHAR(50)默认为空
,类别VARCHAR(50)默认为空
,键入整数默认值为空
,大小整数默认为空
);

这是的后续问题。

根据您的代码,只有当第二次查询(对于$row1下的节点)返回结果时,才会发生DB写入:

for my $row1 ( $xp->findnodes('//row1s/row1') ){
    for my $row2 ( $row1->findnodes('.//row2s/row2') ) {
        $dbh->do("INSERT INTO animal4 (name, category,type,size) VALUES(?,?,?,?)"
        [...]  
        ) or die        ;   
    }
}
如果没有$row2节点,则不存在数据库写入

如果希望在不考虑是否存在$row2节点的情况下进行数据库写入,则需要将数据库写入移出该for循环,即:

for my $row1 ( $xp->findnodes('//row1s/row1') ){
    # get name and category here
    my $name = $row1->getAttribute('name');
    my $cat = $row1->getAttribute('category');
    my $row2set = $row1->find('row2s/row2'); ## creates a Nodeset object
    if ($row2set->size > 0) {
        ## we found nodes!!
        foreach my $row2 ($row2set->get_nodelist) {
           # get size and type here
           my $type = $row2->getAttribute('type');
           my $size = $row2->getAttribute('size');
           # write to db

        }
    } else {
        ## no row2 nodes found.
        ## write to db - just write the row1 values; type and size will be undefined.

    }
}
节点集文档:

关于设置变量和范围的简要说明

作用域是指实体(变量、子例程、对象等)在Perl代码中可见和可访问的位置;设置实体的范围有助于封装它们,并防止数据或函数在程序的每个部分的任何地方都可用

作用域是使用代码结构设置的,例如子例程、循环、包、对象——由大括号(
{
}
分隔的任何代码块)。Perl(和许多其他语言)的标准做法是在进入块时增加缩进,在离开块时减少缩进;这样,您可以在阅读代码时相当容易地确定范围

使用
my
将变量(或函数、对象等)的范围设置为仅限于设置变量的代码块;e、 g

for my $row1 ( $xp->findnodes('//row1s/row1') ){
    # $row1 is available inside this code block

    my $row2set = $row1->find('row2s/row2');
    # $row2set is now available inside this code block

    if ($row2set->size > 0) {
        my $size = $row2set->size;
        # $size is now available inside this code block

        foreach my $row2 ($row2set->get_nodelist) {
            # $row2 is available inside this code block
            # we can also access $row1, $row2set, $size
        }

        # we can access $row1, $row2set, $size
        # $row2 is out of scope, i.e. we cannot access it

        say "The value of row2 is $row2";
        # Perl will complain 'Global symbol "$row2" requires explicit package name'
    }
    # we can access $row1 and $row2set
    # $size and $row2 are out of scope
}
# $row1, $row2set, $size, and $row2 are out of scope
回到您的代码,假设您决定设置变量
$name
$category
$type
$size
,以捕获数据并将其写入数据库。您必须确保正确设置变量的范围,否则它们将存储不适当的数据。例如:

# declare all our variables
my ($name, $cat, $type, $size);
for my $row1 ( $xp->findnodes('//row1s/row1') ){
    # we can set $name and $cat from the data in row1:
    $name = $row1->getAttribute('name');
    $cat = $row1->getAttribute('category');
    my $row2set = $row1->find('row2s/row2');
    if ($row2set->size > 0) {
        foreach my $row2 ($row2set->get_nodelist) {
            # row2 gives us the type and size info
            $type = $row2->getAttribute('type');
            $size = $row2->getAttribute('size');
            # "say" prints a string and adds a "\n" to the end,
            # so it's very handy for debugging
            say "row2s found: name: $name; category: $cat; type: $type; size: $size";
        }
    } else {
        say "row2s empty: name: $name; category: $cat; type: $type; size: $size";
    }
}
这为我们提供了以下输出:

row2s found: name: fox; category: mammal; type: 1; size: 10
row2s found: name: fox; category: mammal; type: 2; size: 8
row2s found: name: horse; category: mammal; type: 3; size: 100
row2s empty: name: bee; category: insect; type: 3; size: 100
row2s empty: name: wasp; category: insect; type: 3; size: 100
这是因为
$type
$size
的范围被设置为整个代码块,并且值在row1循环和内部row2循环的每次迭代之间保留。蜜蜂和黄蜂没有大小和类型的值,因此使用前一种动物的值

有许多不同的方法可以解决此问题,但最有效的方法可能是:

my $db_insert = $dbh->prepare('INSERT INTO animal4 (name, category, type, size) VALUES (?, ?, ?, ?)');

for my $row1 ( $xp->findnodes('//row1s/row1') ){
    my $row2set = $row1->find('row2s/row2');
    if ($row2set->size > 0) {
        foreach my $row2 ($row2set->get_nodelist) {
            # for debugging
            say "row2s found: name: " . $row1->getAttribute('name') .
            "; category: " . $row1->getAttribute('category') .
            "; type: " . $row2->getAttribute('type') .
            "; size: " . $row2->getAttribute('size');

            $db_insert->execute( $row1->getAttribute('name'),
            $row1->getAttribute('category'),
            $row2->getAttribute('type'),
            $row2->getAttribute('size') );
        }
    } else {
        # for debugging
        say "row2s empty: name: " . $row1->getAttribute('name') .
        "; category: " . $row1->getAttribute('category') .
        "; type: NOT SET" .
        "; size: NOT SET";
        $db_insert->execute( $row1->getAttribute('name'),
        $row1->getAttribute('category'),
        undef,
        undef );
    }
}

您已经有了解释和修复,但我建议进行以下更改

  • 您应该
    准备
    插入到
    SQL语句中,然后
    在循环中执行它<代码>执行
    的开销要大得多

  • /
    子代或self::node()
    )XPath构造非常昂贵,您应该将其保留在不知道元素在文档中的位置的情况下,这是非常罕见的。在这种情况下,
    row1
    元素位于
    /database/row1s/row1
    ,而
    row2
    元素位于相对于该行的
    row2s/row2

  • 如果要在带引号的字符串中使用引号字符,则使用不同的分隔符要干净得多。例如
    “我的名字是\“$name\”
    qq{我的名字是“$name”}

这是您的程序版本,可能会有所帮助

use strict;
use warnings;

use XML::XPath;
use DBI;

my $xp = XML::XPath->new( filename => 'animals4.xml' );

my $dbh = DBI->connect(
   'DBI:mysql:test', 'user', 'pw',
   { RaiseError => 1, PrintError => 0}
) or die "Fehler beim Verbidungsaufbau zum MariaDB-Server: $DBI::err -< $DBI::errstr\n";

my $insert_animal = $dbh->prepare('INSERT INTO animal4 (name, category, type, size) VALUES (?, ?, ?, ?)');

for my $row1 ( $xp->findnodes('/database/row1s/row1') ) {

   my $name     = $row1->getAttribute('name');
   my $category = $row1->getAttribute('category');

   printf qq{Level --- row1 "name" gives: $name\n};

   my @row2 = $xp->findnodes('row2s/row2', $row1);

   if ( @row2 ) {
      for my $row2 ( @row2 ) {

         my $type = $row2->getAttribute('type');
         my $size = $row2->getAttribute('size');

         print qq{Level row2 "type" gives: $type\n};
         print qq{Level row2 "size" gives: $size\n};

         $insert_animal->execute($name, $category, $type, $size);
      }
   }
   else {
      $insert_animal->execute($name, $category, undef, undef);
   }
}

无需添加节点集:
my@row2s=$xp->find('.//row2s/row2');如果(@row2s){我的$row2(@row2s){…}其他{…}
@alien谢谢你的代码和解释。真奇怪。当我使用你的代码时,每只动物从所有动物那里得到类型和大小:狐狸(1/10,2/8,3/100);马(1/10,2/8,3/100)、蜜蜂(1/10,2/8,3/100)、黄蜂(1/10,2/8,3/100))。@ikegami感谢这个缩写。我试过了,但是我得到了一条消息(在:Level1--row1“name”给出:fox之后):“找不到对象methid”getAttribute,通过paclage“XML::XPath::NodeSet”在
Level --- row1 "name" gives: fox
Level row2 "type" gives: 1
Level row2 "size" gives: 10
Level row2 "type" gives: 2
Level row2 "size" gives: 8
Level --- row1 "name" gives: horse
Level row2 "type" gives: 3
Level row2 "size" gives: 100
Level --- row1 "name" gives: bee
Level --- row1 "name" gives: wasp