Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.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_Xml Parsing_Xmlreader - Fatal编程技术网

Php 使用XMLreader读取和解析大型XML文件。空值问题

Php 使用XMLreader读取和解析大型XML文件。空值问题,php,xml,xml-parsing,xmlreader,Php,Xml,Xml Parsing,Xmlreader,我需要读取大约1GB大小的XML文件。我的XML: <products> <product> <categoryName>Kable i konwertery AV</categoryName> <brandName>Belkin</brandName> <productCode>AV10176bt1M-BLK</productCode> <productId>5616488</pr

我需要读取大约1GB大小的XML文件。我的XML:

<products>
<product>
<categoryName>Kable i konwertery AV</categoryName>
<brandName>Belkin</brandName>
<productCode>AV10176bt1M-BLK</productCode>
<productId>5616488</productId>
<productFullName>Kabel Belkin Kabel HDMI Ultra HD High Speed 1m-AV10176bt1M-BLK</productFullName>
<productEan>0745883767465</productEan>
<productEuroPriceNetto>59.71</productEuroPriceNetto>
<productFrontendPriceNetto>258.54</productFrontendPriceNetto>
<productFastestSupplierQuantity>23</productFastestSupplierQuantity>
<deliveryEstimatedDays>2</deliveryEstimatedDays>
</product>
<product>
<categoryName>Telewizory</categoryName>
<brandName>Sony</brandName>
<productCode>KDL32WD757SAEP</productCode>
<productId>1005662</productId>
<productFullName>Telewizor Sony KDL-32WD757 SAEP</productFullName>
<productEan></productEan>
<productEuroPriceNetto>412.33</productEuroPriceNetto>
<productFrontendPriceNetto>1785.38</productFrontendPriceNetto>
<productFastestSupplierQuantity>11</productFastestSupplierQuantity>
<deliveryEstimatedDays>6</deliveryEstimatedDays>
</product>
<product>
<categoryName>Kuchnie i akcesoria</categoryName>
<brandName>Brimarex</brandName>
<productCode>1566287</productCode>
<productId>885156</productId>
<productFullName>Brimarex Drewniane owoce, Kiwi - 1566287</productFullName>
<productEan></productEan>
<productEuroPriceNetto>0.7</productEuroPriceNetto>
<productFrontendPriceNetto>3.05</productFrontendPriceNetto>
<productFastestSupplierQuantity>7</productFastestSupplierQuantity>
<deliveryEstimatedDays>3</deliveryEstimatedDays>
</product>
</products>
除了一个问题外,一切正常。。。当某个值丢失时,例如输出中的
,我将从上一个非空标记获得一个值,直到另一个非空标记

例如,如果前一个节点与示例
0745883767465
中的节点类似,并且另外两个
在获得相同值的输出数组I中为空,
07458837465


解决这个问题的正确方法是什么?或者某个人有工作解决方案…

重置每个循环上的所有变量。看起来,如果您没有为它指定任何值,它将获得先前指定的值

<?php 
while($reader->read()) {
    $categoryName = 
    $brandName = 
    $productCode = 
    $productId = 
    $productFullName = 
    $productEan = 
    $productEuroPriceNetto = 
    $productFastestSupplierQuantity = 
    $deliveryEstimatedDays = '';
//... code
}
?>

重置每个循环上的所有变量。看起来,如果您没有为它指定任何值,它将获得先前指定的值

<?php 
while($reader->read()) {
    $categoryName = 
    $brandName = 
    $productCode = 
    $productId = 
    $productFullName = 
    $productEan = 
    $productEuroPriceNetto = 
    $productFastestSupplierQuantity = 
    $deliveryEstimatedDays = '';
//... code
}
?>

这里有一些代码可以满足您的需要。当遇到
TEXT
CDATA
节点时,它保存每个元素的值,然后在到达
END\u元素时存储该值。此时,保存的值被设置为
'
,这样,如果找不到元素的值,它将获得一个空字符串(如果愿意,可以将其更改为
null
)。它还处理自动关闭标记,例如在找到
元素
节点时使用
isEmptyElement
检查。它利用PHPs变量来避免代码中的长序列
if($nodename==…)
,而且还使用数组来存储每个产品的值,从长远来看,我认为这是解决问题的更好方法

$reader = new XMLReader();
$reader->xml($xml);
$count = 0;
$this_value = '';
$products = array();
while($reader->read()) {
    switch ($reader->nodeType) {
        case XMLReader::ELEMENT:
            // deal with self-closing tags e.g. <productEan />
            if ($reader->isEmptyElement) {
                ${$reader->name} = '';
                $products[$count][$reader->name] = '';
            }
            break;
        case XMLReader::TEXT:
        case XMLReader::CDATA:
            // save the value for storage when we get to the end of the element
            $this_value = $reader->value;
            break;
        case XMLReader::END_ELEMENT:
            if ($reader->name == 'product') {
                $count++;
                print_r(array($categoryName, $brandName, $productCode, $productId, $productFullName, $productEan, $productEuroPriceNetto, $productFrontendPriceNetto, $productFastestSupplierQuantity, $deliveryEstimatedDays));
            }
            elseif ($reader->name != 'products') {
                ${$reader->name} = $this_value;
                $products[$count][$reader->name] = $this_value;
                // set this_value to a blank string to allow for empty tags
                $this_value = '';
            }
            break;
        case XMLReader::WHITESPACE:
        case XMLReader::SIGNIFICANT_WHITESPACE:
        default:
            // nothing to do
            break;
    }
}
$reader->close();
print_r($products);
$reader=newXMLReader();
$reader->xml($xml);
$count=0;
$this_值='';
$products=array();
而($reader->read()){
开关($reader->nodeType){
案例XMLReader::元素:
//处理自动关闭标签,例如。
如果($reader->isemptyelment){
${$reader->name}='';
$products[$count][$reader->name]='';
}
打破
案例XMLReader::文本:
案例XMLReader::CDATA:
//当我们到达元素末尾时,保存值以供存储
$this_value=$reader->value;
打破
案例XMLReader::END_元素:
如果($reader->name=='product'){
$count++;
打印(数组($categoryName、$brandName、$productCode、$productId、$productFullName、$productEan、$productEuroPriceNetto、$productFrontendPriceNetto、$productFastestSupplierQuantity、$deliveryEstimatedDays));
}
elseif($reader->name!=“产品”){
${$reader->name}=$this_值;
$products[$count][$reader->name]=$this\u值;
//将此_值设置为空字符串以允许空标记
$this_值='';
}
打破
大小写XMLReader::空白:
案例XMLReader::重要的_空格:
违约:
//无事可做
打破
}
}
$reader->close();
印刷品(产品);

我省略了输出,因为它很长,但是您可以在这里看到正在运行的代码。

这里有一些代码可以满足您的需要。当遇到
TEXT
CDATA
节点时,它保存每个元素的值,然后在到达
END\u元素时存储该值。此时,保存的值被设置为
'
,这样,如果找不到元素的值,它将获得一个空字符串(如果愿意,可以将其更改为
null
)。它还处理自动关闭标记,例如在找到
元素
节点时使用
isEmptyElement
检查。它利用PHPs变量来避免代码中的长序列
if($nodename==…)
,而且还使用数组来存储每个产品的值,从长远来看,我认为这是解决问题的更好方法

$reader = new XMLReader();
$reader->xml($xml);
$count = 0;
$this_value = '';
$products = array();
while($reader->read()) {
    switch ($reader->nodeType) {
        case XMLReader::ELEMENT:
            // deal with self-closing tags e.g. <productEan />
            if ($reader->isEmptyElement) {
                ${$reader->name} = '';
                $products[$count][$reader->name] = '';
            }
            break;
        case XMLReader::TEXT:
        case XMLReader::CDATA:
            // save the value for storage when we get to the end of the element
            $this_value = $reader->value;
            break;
        case XMLReader::END_ELEMENT:
            if ($reader->name == 'product') {
                $count++;
                print_r(array($categoryName, $brandName, $productCode, $productId, $productFullName, $productEan, $productEuroPriceNetto, $productFrontendPriceNetto, $productFastestSupplierQuantity, $deliveryEstimatedDays));
            }
            elseif ($reader->name != 'products') {
                ${$reader->name} = $this_value;
                $products[$count][$reader->name] = $this_value;
                // set this_value to a blank string to allow for empty tags
                $this_value = '';
            }
            break;
        case XMLReader::WHITESPACE:
        case XMLReader::SIGNIFICANT_WHITESPACE:
        default:
            // nothing to do
            break;
    }
}
$reader->close();
print_r($products);
$reader=newXMLReader();
$reader->xml($xml);
$count=0;
$this_值='';
$products=array();
而($reader->read()){
开关($reader->nodeType){
案例XMLReader::元素:
//处理自动关闭标签,例如。
如果($reader->isemptyelment){
${$reader->name}='';
$products[$count][$reader->name]='';
}
打破
案例XMLReader::文本:
案例XMLReader::CDATA:
//当我们到达元素末尾时,保存值以供存储
$this_value=$reader->value;
打破
案例XMLReader::END_元素:
如果($reader->name=='product'){
$count++;
打印(数组($categoryName、$brandName、$productCode、$productId、$productFullName、$productEan、$productEuroPriceNetto、$productFrontendPriceNetto、$productFastestSupplierQuantity、$deliveryEstimatedDays));
}
elseif($reader->name!=“产品”){
${$reader->name}=$this_值;
$products[$count][$reader->name]=$this\u值;
//将此_值设置为空字符串以允许空标记
$this_值='';
}
打破
大小写XMLReader::空白:
案例XMLReader::重要的_空格:
违约:
//无事可做
打破
}
}
$reader->close();
印刷品(产品);

我省略了输出,因为它很长,但您可以在其中看到正在运行的代码。

如果不使用单个值,而是将值存储在一个详细信息数组中,则可以在处理每个元素后将数组清空

$reader->open($url);
$count = 0;

$data = [];
while($reader->read()) {
    if($reader->nodeType == XMLReader::ELEMENT)
        $nodeName = $reader->name;

        if(($reader->nodeType == XMLReader::TEXT || $reader->nodeType == XMLReader::CDATA)) {
            $data[$nodeName] = $reader->value;
        }

        if($reader->nodeType == XMLReader::END_ELEMENT && $reader->name == 'product') {
            // Process data
            echo ($data['productEan']??"Empty").PHP_EOL;
            // Reset
            $data = [];
            $count++;
        }
}
$reader->close();
这与你的测试数据给出

0745883767465
Empty
Empty

如果不使用单个值,而是将值存储在详细信息数组中,则可以将该数组清空一次