У меня есть этот XML-канал ниже, я пытаюсь импортировать в MySQL для всех продуктов.
Например, внутри таблицы XML_FEED
Я хочу что-то вроде
shop - product_id - product_name - product_link - .......
mywebstore - 322233 - MadBiker 600 - .........
mywebstore - 324633 - Samsung S4 - .........
Код до сих пор работает, только если XML начинается с <products>
а не из <mywebstore>
Как изменить мой код, чтобы сделать это?
$xml = simplexml_load_file("test.xml");
foreach($xml->product as $product)
{
$columns = array();
$data = array();
foreach($product->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
$columns[] = $child->getName();
$data[] = mysql_real_escape_string((string)$child);
}
$col = '`'. implode('`,`',$columns) .'`';
$val = "'". implode("','",$data)."'";
$query = "INSERT INTO XML_FEED ($col) VALUES ($val)";
echo $query;
mysql_query($query);
}
Вот XML:
<?xml version="1.0" encoding="UTF-8"?>
<mywebstore>
<created_at>2010-04-08 12:32</created_at>
<products>
<product>
<id>322233</id>
<name><![CDATA[MadBiker 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
...
...
...
</products>
</mywebstore>
Это должно работать для вас:
<?php
//Xml stuff
$xml = simplexml_load_file("file.xml");
//Database stuff
$hostname = "localhost";
$username = "root";
$password = "";
try {
//DB Connection
$dbh = new PDO("mysql:host=$hostname;dbname=dbname", $username, $password);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected to Database<br/>";foreach($xml->products->product as $data) {
$sql = "INSERT INTO XML_FEED (shop, product_id, product_name, product_link, product_image, product_category, product_price_with_vat)
VALUES (:SHOP, :ID, :NAME, :LINK, :IMAGE, :CATEGORY, :PRICE)";
$stmt = $dbh->prepare($sql);
$params = array(
"SHOP" => $xml->getName(),
"ID" => $data->id ,
"NAME" => $data->name,
"LINK" => $data->link,
"IMAGE" => $data->image,
"CATEGORY" => $data->category,
"PRICE" => $data->price_with_vat
);
$stmt->execute($params);
}
//Close Connection
$dbh = null;
} catch(PDOException $e) {
echo $e->getMessage();
}
?>
Примечание сайта:
Добавьте отчет об ошибках в начало файла (ов), который поможет во время производственного тестирования.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
?>
Также, если вы хотите показать / увидеть данные в формате HTML, вы можете использовать это:
<?php
//Xml stuff
$xml = simplexml_load_file("file.xml");
echo "<table border='1'>";
echo "<tr>
<td>Shop</td>
<td>Product ID</td>
<td>Product Name</td>
<td>Product Link</td>
<td>Product Image</td>
<td>Product Category</td>
<td>Product Price with vat</td>
</tr>";
foreach($xml->products->product as $data) {
echo "<tr>
<td>" . $xml->getName() . "</td>
<td>" . $data->id . "</td>
<td>" . $data->name . "</td>
<td>" . $data->link . "</td>
<td>" . $data->image . "</td>
<td>" . $data->category . "</td>
<td>" . $data->price_with_vat. "</td>
</tr>";
}
echo "</table>";
?>
Используйте этот код:
<?php
$xml = simplexml_load_file('test.xml');
foreach($xml->products->product as $product)
{
$columns = array();
$data = array();
foreach($product->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
$columns[] = $child->getName();
$data[] = mysql_real_escape_string((string)$child);
}
$col = '`'. implode('`,`',$columns) .'`';
$val = "'". implode("','",$data)."'";
$query = "INSERT INTO XML_FEED ($col) VALUES ($val)";
echo $query;
mysql_query($query);
}
?>
Вы не можете получить данные из-за отсутствия или неверного родительского узла.
При работе с XML необходимо обрабатывать родительский и дочерний (дочерний) узел
отношения тщательно. К сожалению, вы пропустили то же самое
вещь.
В вашем коде вы обработали второе условие. Вы должны обработать оба условия, или вы можете использовать первое условие в вашем коде.
Пример:
<?php
$file = 'test.xml';
$xml = simplexml_load_file($file, null, LIBXML_NOCDATA);
if($xml === false){
echo "Failed to load '$file'.\n";
}else{
$productsArr = Array();
if(isset($xml->products)){
$productsArr = $xml->products;
}else if(isset($xml->product)){
$productsArr = $xml;
}
if(sizeof($productsArr) > 0){
foreach($productsArr->product as $productArr){
$productArr = (array) $productArr;
$id = null;
if(isset($productArr['@attributes'])){
$id = $productArr['@attributes']['id'];
unset($productArr['@attributes']);
}
if(!isset($productArr['id']) && !empty($id)){
$productArr['id'] = $id;
}
array_walk_recursive($productArr, function (&$value) {
$value = htmlentities($value,ENT_QUOTES,'UTF-8');
$value = mysql_real_escape_string($value);
});
$col = '`'. implode('`,`',array_keys($productArr)) .'`';
$val = "'". implode("','",array_values($productArr))."'";
$query = "INSERT INTO projectx ($col) VALUES ($val)";
echo "$query \n";
mysql_query($query);
}
}else{
echo "Invalid XML Format.Missing parent node '<mywebstore> or <products>'. \n";
}
}
XML:
<mywebstore>
как родительский узел XML с идентификатором атрибута:`
<?xml version="1.0" encoding="UTF-8"?>
<mywebstore>
<created_at>2010-04-08 12:32</created_at>
<products>
<product id="322233">
<name><![CDATA[MadBiker' 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
<product>
<id>322234</id>
<name><![CDATA[MadBiker 700]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>344.00</price_with_vat>
</product>
</products>
</mywebstore>
<mywebstore>
как родительский узел XML без идентификатора атрибута (такой же, как вопрос XML):`
<?xml version="1.0" encoding="UTF-8"?>
<mywebstore>
<created_at>2010-04-08 12:32</created_at>
<products>
<product>
<id>322233</id>
<name><![CDATA[MadBiker 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
</products>
</mywebstore>
`
<products>
как родительский узел XML с идентификатором атрибута:`
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product id="322233">
<name><![CDATA[MadBiker' 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
<product>
<id>322234</id>
<name><![CDATA[MadBiker 700]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>344.00</price_with_vat>
</product>
</products>
`
<products>
как родительский узел XML без атрибута (ID):`
<?xml version="1.0" encoding="UTF-8"?>
<products>
<product>
<id>322233</id>
<name><![CDATA[MadBiker 600]]></name>
<link><![CDATA[http://www.mywebstore.co.uk/product/322233]]></link>
<image><![CDATA[http://www.mywebstore.co.uk/product/322233.jpg]]></image>
<category><![CDATA[Outdor > Extreme Sports]]></category>
<price_with_vat>322.33</price_with_vat>
</product>
</products>
Заключение: В правильном обращении с родителями & отношения дочернего узла.
Просто измените это:
foreach($xml->product as $product)
{
с этим:
foreach($xml->products[0] as $product)
{
Для того, чтобы получить различные продукты, вы должны использовать XPath
Код:
$xml = simplexml_load_file("xml.xml");
// will search for array of products no matter what it is nested inside of
$products = $xml->xpath('//product');
foreach($products as $product)
{
$columns = array();
$data = array();
foreach($product->children() as $child)
{
echo $child->getName() . ": " . $child . "<br />";
$columns[] = $child->getName();
$data[] = mysql_real_escape_string((string)$child);
}
$col = '`'. implode('`,`',$columns) .'`';
$val = "'". implode("','",$data)."'";
$query = "INSERT INTO XML_FEED ($col) VALUES ($val)";
echo $query;
mysql_query($query);
}
Объяснение:
Xpath для simplexml просто возвращает массив простых xml-объектов или здесь xml-элементов продукта.
Так как мы хотим вернуть массив всех продуктов, мы ищем вхождение «foreach» продукта, используя xpath.
Внутри строки xpath двойная косая черта (//) означает, что возвращаются все элементы в документе XML, которые соответствуют критериям поиска, независимо от местоположения / уровня в документе.
Во-первых, simplexml_load_file()
возвращает указатель на корень элемент ленты XML, т. е. самый первый тег XML во входном файле. Другими словами, когда вы пишете:
$xml = simplexml_load_file("test.xml");
test.xml
содержит «<mywebstore> <products> <product> (...)
» затем $xml
указывает на <mywebstore>
test.xml
содержит «<products> <product> (...)
» затем $xml
указывает на <products>
Во-вторых, $xml->[tagName]
ищет непосредственный только дети, а не рекурсивно. Следовательно $xml->product
находит что-то, только если <product>
тег существует как дочерний элемент корневого элемента.
В целом, лучше, чтобы код точно соответствовал структуре ввода. Адаптируйте ваш внешний цикл к ожидаемому входу:
foreach($xml->product as $product) {
...
}
или же
foreach($xml->products->product as $product) {
...
}
Если по какой-то причине <products>
тег может находиться в разных местах входного XML-канала, возможно, выполнить в два этапа:
// try to locate the <product> nodes
if (count($xml->product) !== 0) {
$productNodes = $xml->product;
} else if (count($xml->products->product) !== 0) {
$productNodes = $xml->products->product;
} else {
throw new Exception('No <product> node found');
}
// do the job
foreach($productNodes as $product){
...
}
Или для чрезвычайной гибкости, используйте xpath. Ниже вернется список всех <product>
узлы в любом месте в канале XML.
$productNodes = $xml->xpath('//product');
foreach($productNodes as $product){
...
}
Я верю, что часть MySQL не является проблемой, поэтому я просто придерживаюсь обычного заклинания:
Пожалуйста, не используйте
mysql_*
функции в новом коде. Они больше не поддерживаются и официально устарели. Увидеть красная коробка? Узнать о готовые заявления вместо этого и использовать PDO или же MySQLi — Эта статья поможет вам решить, какой. Если вы выбираете PDO, вот хороший урок.