Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/239.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
Php 如何使用XMLReader解析XML元素/子元素的多个同名属性_Php_Xml_Xmlreader - Fatal编程技术网

Php 如何使用XMLReader解析XML元素/子元素的多个同名属性

Php 如何使用XMLReader解析XML元素/子元素的多个同名属性,php,xml,xmlreader,Php,Xml,Xmlreader,我使用XMLReader和PHP处理一个中等大小的XML文件(6mb),基本上分解属性数据并将其插入到我自己的数据库中。问题是,每个元素都有数量可变的子元素,这些子元素的属性名称相同 以下是一个示例(这是govtrack.us提供的有关政府的公开数据): 为了得到“id”,它给了我两次,在元素中有多少子元素,就用多少换行符分开(我认为上面的注释说明了这一点,但我不确定该怎么办) 2) 如何按顺序访问每个子元素的属性?这: $p->getAttribute('startdate') 提供由

我使用XMLReader和PHP处理一个中等大小的XML文件(6mb),基本上分解属性数据并将其插入到我自己的数据库中。问题是,每个元素都有数量可变的子元素,这些子元素的属性名称相同

以下是一个示例(这是govtrack.us提供的有关政府的公开数据):

为了得到“id”,它给了我两次,在元素中有多少子元素,就用多少换行符分开(我认为上面的注释说明了这一点,但我不确定该怎么办)

2) 如何按顺序访问每个子元素的属性?这:

$p->getAttribute('startdate')
提供由多个换行符分隔的每个“startdate”值。我只需要获取元素的id,然后循环遍历每个“角色”子元素

有什么想法吗

为了启发大家,这里是我迄今为止拥有的超级简单控制器:

$f = base_url().'data/people.xml';
$p = new XMLReader;
$p->open($f);
while($p->read())
{
    if($this->_notImported('govtrack',$p->getAttribute('id')))
    {
            // here I just grab the attributes, put them into arrays to insert, like so:
            $insert = array('indiv_name' => $full_name,
                                    'indiv_first' => ($p->getAttribute(‘firstname’)),
                                    'indiv_last' => ($p->getAttribute(‘lastname’)),
                                    'indiv_middle' => ($p->getAttribute(‘middlename’)),
                                    'indiv_other' => ($p->getAttribute(‘namemod’)),
                                    'indiv_full_name' => $full_name,
                                    'indiv_title' => ($p->getAttribute(‘title’)),
                                    'indiv_dob' => ($p->getAttribute(‘birthday’)),
                                    'indiv_gender' => ($p->getAttribute(‘gender’)),
                                    'indiv_religion' => ($p->getAttribute(‘religion’)),
                                    'indiv_url' => ($url)
                                    );

对于元素来说,这并没有那么困难,但我不知道如何循环遍历每个“角色”子元素并分别获取属性。

您的第一个问题是没有检查适当的节点类型,这实际上与您链接的注释有关:它与开头标记(元素)都匹配和结束标记(结束元素)

您的第二个问题也与缺少节点类型检查有关。修复后,只需检查节点的名称,以确定它是
还是

因为我假设您也在读取一个大的XML文件,所以您可能想知道何时传递给下一个person标记。。。(通过END_元素nodeType)参见下面的示例:

while($p->read()) {
    // check for nodeType here (opening tag only)
    if ($p->nodeType == XMLReader::ELEMENT) {
        if ($p->name == 'person') {
            if ($this->_notImported('govtrack',$p->getAttribute('id'))) {
                // $insert['indiv_*'] stuff here
            } else {
                $insert = null; // skip record because it's already imported
            }
        } else if ($p->name == 'role') {
            // role stuff here
            $startdate = $p->getAttribute('startdate');
        }

    // check for closing </person> tag here
    } else if ($p->nodeType == XMLReader::END_ELEMENT && $p->name == 'person') {
        if (isset($insert)) {
            // db insert here
        }
    }
}
while($p->read()){
//在此处检查节点类型(仅限开始标记)
如果($p->nodeType==XMLReader::ELEMENT){
如果($p->name=='person'){
如果($this->\u notImported('govtrack',$p->getAttribute('id')){
//$insert['indiv\*']在此处插入内容
}否则{
$insert=null;//跳过记录,因为它已导入
}
}如果($p->name=='role'){
//这里的角色
$startdate=$p->getAttribute('startdate');
}
//检查此处的结束标记
}如果($p->nodeType==XMLReader::END_元素&&$p->name==person'),则为else{
如果(isset($insert)){
//在这里插入数据库
}
}
}

顺便说一句,如果你想让它起作用,你的引号必须用正确的引号替换。

太棒了!!我在内存分配方面仍然有一些问题,但这工作得更好,我想我已经走上了让它工作的轨道。(我不确定我的引用发生了什么;它们在我的实际代码中是正确的,只是不是如此)。
$f = base_url().'data/people.xml';
$p = new XMLReader;
$p->open($f);
while($p->read())
{
    if($this->_notImported('govtrack',$p->getAttribute('id')))
    {
            // here I just grab the attributes, put them into arrays to insert, like so:
            $insert = array('indiv_name' => $full_name,
                                    'indiv_first' => ($p->getAttribute(‘firstname’)),
                                    'indiv_last' => ($p->getAttribute(‘lastname’)),
                                    'indiv_middle' => ($p->getAttribute(‘middlename’)),
                                    'indiv_other' => ($p->getAttribute(‘namemod’)),
                                    'indiv_full_name' => $full_name,
                                    'indiv_title' => ($p->getAttribute(‘title’)),
                                    'indiv_dob' => ($p->getAttribute(‘birthday’)),
                                    'indiv_gender' => ($p->getAttribute(‘gender’)),
                                    'indiv_religion' => ($p->getAttribute(‘religion’)),
                                    'indiv_url' => ($url)
                                    );
while($p->read()) {
    // check for nodeType here (opening tag only)
    if ($p->nodeType == XMLReader::ELEMENT) {
        if ($p->name == 'person') {
            if ($this->_notImported('govtrack',$p->getAttribute('id'))) {
                // $insert['indiv_*'] stuff here
            } else {
                $insert = null; // skip record because it's already imported
            }
        } else if ($p->name == 'role') {
            // role stuff here
            $startdate = $p->getAttribute('startdate');
        }

    // check for closing </person> tag here
    } else if ($p->nodeType == XMLReader::END_ELEMENT && $p->name == 'person') {
        if (isset($insert)) {
            // db insert here
        }
    }
}