xml2mysql致命错误:调用成员函数item()

gg58donl  于 2021-06-17  发布在  Mysql
关注(0)|答案(2)|浏览(309)

实际上,我正在尝试将xml导入mysql

for ($i=0; $i < $itemCount; $i++) {
    $title = $xmlObject->item($i)->getElementsByTagName('title')->item(0)->childNodes->item(0)->nodeValue;
    $link  = $xmlObject->item($i)->getElementsByTagName('link')->item(0)->childNodes->item(0)->nodeValue;
    $image_link  = $xmlObject->item($i)->getElementsByTagName('image_link')->item(0)->childNodes->item(0)->nodeValue;
    $price  = $xmlObject->item($i)->getElementsByTagName('price')->item(0)->childNodes->item(0)->nodeValue;
    $brand  = $xmlObject->item($i)->getElementsByTagName('brand')->item(0)->childNodes->item(0)->nodeValue;
    $availability = $xmlObject->item($i)->getElementsByTagName('availability')->item(0)->childNodes->item(0)->nodeValue;  
    $id = $xmlObject->item($i)->getElementsByTagName('id')->item(0)->childNodes->item(0)->nodeValue;  
    $product_type = $xmlObject->item($i)->getElementsByTagName('product_type')->item(0)->childNodes->item(0)->nodeValue;  
    $description = $xmlObject->item($i)->getElementsByTagName('description')->item(0)->childNodes->item(0)->nodeValue;  
    $sale_price = $xmlObject->item($i)->getElementsByTagName('sale_price')->item(0)->childNodes->item(0)->nodeValue;

添加最后一个对象后 Saleprice 我收到了错误信息
致命错误:在中对null调用成员函数item()
我认为问题是“销售价格”的价值并不是每个项目都有
但是我该怎么解决这个问题呢?如果设置了值>这个值就会被导入mysql
提前谢谢
xml示例

<item>
    <g:id>4</g:id>
    <title>sadsadsdsadsadsadsadasd</title>
    <description>dddddddd</description>
    <g:product_type>aaaaaaaaa</g:product_type>
    <link>https://www.xyz.de</link>
    <g:image_link>https://www.xyz.de/600x600.jpg</g:image_link>
    <g:condition>new</g:condition>
    <g:availability>out of stock</g:availability>
            <g:price>5,95</g:price>
        <g:sale_price>4,99</g:sale_price>
        <g:brand>asdasdsddsn</g:brand>
    <g:gtin>137</g:gtin>
    <g:mpn></g:mpn>
    <g:shipping>
        <g:country>DE</g:country>
        <g:service>Standard</g:service>
        <g:price>7,99</g:price>
    </g:shipping>
    <pubDate>Fri, 07 Dec 2018 12:10:02 CET</pubDate></item>
ztyzrc3y

ztyzrc3y1#

您将访问列表的第一个节点,而不检查列表是否有节点。

$sale_price =  
  $xmlObject // DOM node list
    ->item($i) // DOM node at index $i
    ->getElementsByTagName('sale_price') // list of'sale_price' descendant elements
    ->item(0) // first node in list - NULL if list is empty
    ->childNodes // child nodes list - this includes text nodes
    ->item(0)  // first node in list - NULL if list is empty
    ->nodeValue; // node content

如果这里没有 sale_price 元素(在一个上下文节点中)。因此,如果使用dom方法,则必须检查每个级别以避免这种情况。
或者开始使用xpath:

$xml = <<<'XML'
<products>
  <product>
    <title>With sale_price</title>
    <sale_price>42.00</sale_price>
  </product>
  <product>
    <title>Without sale_price</title>
  </product>
</products>
XML;

$document = new \DOMDocument();
$document->loadXML($xml);
$xpath = new \DOMXpath($document);

foreach($xpath->evaluate('//product') as $product) {
    echo $xpath->evaluate('string(title)', $product), ': ';
    echo $xpath->evaluate('string(sale_price)', $product), "\n";
}

输出:

With sale_price: 42.00 
Without sale_price:
``` `DOMXpath::evaluate()` 可以返回带有位置路径表达式的节点列表,如 `//product` 以及标量值(如果在表达式中强制转换节点列表)。 `string(title)` 将获取所有 `title` 将子节点转换为列表,并将第一个节点转换为字符串(返回其文本内容),如果找不到节点,则返回空字符串。
piztneat

piztneat2#

有两种方法可以实现这一点,您目前正在做的方法可以缩短,这样就没有那么多代码了。在sale\ u price中,它获取一个元素列表,如果没有,则默认为0。。。

for ($i=0; $i < $itemCount; $i++) {
    $title = $xmlObject->item($i)->getElementsByTagName('title')->item(0)->nodeValue;
    $link  = $xmlObject->item($i)->getElementsByTagName('link')->item(0)->nodeValue;
    $image_link  = $xmlObject->item($i)->getElementsByTagName('image_link')->item(0)->nodeValue;
    $price  = $xmlObject->item($i)->getElementsByTagName('price')->item(0)->nodeValue;
    $brand  = $xmlObject->item($i)->getElementsByTagName('brand')->item(0)->nodeValue;
    $availability = $xmlObject->item($i)->getElementsByTagName('availability')->item(0)->nodeValue;
    $id = $xmlObject->item($i)->getElementsByTagName('id')->item(0)->nodeValue;
    $product_type = $xmlObject->item($i)->getElementsByTagName('product_type')->item(0)->nodeValue;
    $description = $xmlObject->item($i)->getElementsByTagName('description')->item(0)->nodeValue;
    $sale_price = $xmlObject->item($i)->getElementsByTagName('sale_price');
    $sale_price =  ( count($sale_price) > 0 )? $sale_price->item(0)->nodeValue : 0;

    $sql   = "Insert into xxxxxxxxx (title, link, image_link, price, brand, availability, id, product_type, description, sale_price) VALUE ('$title', '$link', '$image_link', '$price', '$brand', '$availability', '$id', '$product_type', '$description', '$sale_price')";
    echo $sql.PHP_EOL;
}

或者您可以切换到simplexml,它的代码要少得多。在这里您可以使用php的 isset() 检查是否有值,如果没有则设置为0。在php7中,还可以使用null coalesce( ?? )做同样的事。。。

$xml = simplexml_load_file("data.xml");   // Load from a file
// $xml = simplexml_load_string($xmlData);   // Load from a string
foreach ( $xml->item as $item ) {
    $g = $item->children("g", true);

    $title = (string)$item->title;
    $link  = (string)$item->link;
    $image_link  = (string)$g->image_link;
    $price  = (string)$g->price;
    $brand  = (string)$g->brand;
    $availability = (string)$g->availability;
    $id = (string)$g->id;
    $product_type = (string)$g->product_type;
    $description = (string)$item->description;
    $sale_price = (string)(isset($g->sale_price) ?$g->sale_price: 0);
    // $sale_price = (string)($g->sale_price ?? 0);   // PHP 7+

    $sql   = "Insert into xxxxxxxxx (title, link, image_link, price, brand, availability, id, product_type, description, sale_price) VALUE ('$title', '$link', '$image_link', '$price', '$brand', '$availability', '$id', '$product_type', '$description', '$sale_price')";
    echo $sql.PHP_EOL;
}

simplexml中唯一的复杂之处是它必须考虑名称空间,因此任何带有g前缀(例如id)的元素都需要从名称空间中读取 $g 变量,它是节点中所有以g为前缀的元素。

相关问题