实际我试图将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>
您将访问列表的第一个节点,而不检查列表是否有节点。
$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
子节点提取到一个列表中,并将第一个节点转换为字符串(返回其文本内容),如果找不到节点,它将返回一个空字符串。
有几种方法可以解决这个问题,你目前的做法可以缩短,这样就不会有那么多代码。 使用 sale_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。 在 PHP 7 中,你也可以使用空合并 (??
) 来做同样的事情...
$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前缀的元素。