Как Excel читает файл XML?

Я много исследовал, чтобы преобразовать XML-файл в 2d-массив таким же образом, как Excel пытается создать тот же алгоритм, что и Excel, когда вы открываете XML-файл в Excel.

<items>
<item>
<sku>abc 1</sku>
<title>a book 1</title>
<price>42 1</price>
<attributes>
<attribute>
<name>Number of pages 1</name>
<value>123 1</value>
</attribute>
<attribute>
<name>Author 1</name>
<value>Rob dude 1</value>
</attribute>
</attributes>
<contributors>
<contributor>John 1</contributor>
<contributor>Ryan 1</contributor>
</contributors>
<isbn>12345</isbn>
</item>
<item>
<sku>abc 2</sku>
<title>a book 2</title>
<price>42 2</price>
<attributes>
<attribute>
<name>Number of pages 2</name>
<value>123 2</value>
</attribute>
<attribute>
<name>Author 2</name>
<value>Rob dude 2</value>
</attribute>
</attributes>
<contributors>
<contributor>John 2</contributor>
<contributor>Ryan 2</contributor>
</contributors>
<isbn>6789</isbn>
</item>
</items>

Я хочу, чтобы он преобразовал его в 2-мерный массив, как если бы вы открыли тот же файл в Excel, он покажет вам, как это

введите описание изображения здесь


Я хочу преобразовать в 2-мерный массив, как в Excel. Пока я могу извлечь ярлыки, как это делает Excel

function getColNames($array) {
$cols   = array();
foreach($array as $key=>$val) {
if(is_array($val)) {
if($val['type']=='complete') {
if(in_array($val['tag'], $cols)) {

} else {
$cols[] = $val['tag'];
}
}
}
}
return $cols;
}

$p = xml_parser_create();
xml_parse_into_struct($p, $simple, $vals, $index);
xml_parser_free($p);

Цель

Я хочу, чтобы это генерировалось вот так ..

array (
0 => array (
'sku'=>'abc 1',
'title'=>'a book 1',
'price'=>'42 1',
'name'=>'Number of Pages 1',
'value'=>'123 1',
'isbn'=>12345
),
1 => array (
'sku'=>'abc 1',
'title'=>'a book 1',
'price'=>'42 1',
'name'=>'Author 1',
'value'=>'Rob dude 1',
'isbn'=>12345
),
2 => array (
'sku'=>'abc 1',
'title'=>'a book 1',
'price'=>'42 1',
'contributor'=>'John 1',
'isbn'=>12345
),
3 => array (
'sku'=>'abc 1',
'title'=>'a book 1',
'price'=>'42 1',
'contributor'=>'Ryan 1',
'isbn'=>12345
),
)

Образец 2 XML ..

 <items>
<item>
<sku>abc 1</sku>
<title>a book 1</title>
<price>42 1</price>
<attributes>
<attribute>
<name>Number of pages 1</name>
<value>123 1</value>
</attribute>
<attribute>
<name>Author 1</name>
<value>Rob dude 1</value>
</attribute>
</attributes>
<contributors>
<contributor>John 1</contributor>
<contributor>Ryan 1</contributor>
</contributors>
<isbns>
<isbn>12345a</isbn>
<isbn>12345b</isbn>
</isbns>
</item>
<item>
<sku>abc 2</sku>
<title>a book 2</title>
<price>42 2</price>
<attributes>
<attribute>
<name>Number of pages 2</name>
<value>123 2</value>
</attribute>
<attribute>
<name>Author 2</name>
<value>Rob dude 2</value>
</attribute>
</attributes>
<contributors>
<contributor>John 2</contributor>
<contributor>Ryan 2</contributor>
</contributors>
<isbns>
<isbn>6789a</isbn>
<isbn>6789b</isbn>
</isbns>
</item>
</items>

Образец 3 XML ..

<items>
<item>
<sku>abc 1</sku>
<title>a book 1</title>
<price>42 1</price>
<attributes>
<attribute>
<name>Number of pages 1</name>
<value>123 1</value>
</attribute>
<attribute>
<name>Author 1</name>
<value>Rob dude 1</value>
</attribute>
</attributes>
<contributors>
<contributor>John 1</contributor>
<contributor>Ryan 1</contributor>
</contributors>
<isbns>
<isbn>
<name>isbn 1</name>
<value>12345a</value>
</isbn>
<isbn>
<name>isbn 2</name>
<value>12345b</value>
</isbn>
</isbns>
</item>
<item>
<sku>abc 2</sku>
<title>a book 2</title>
<price>42 2</price>
<attributes>
<attribute>
<name>Number of pages 2</name>
<value>123 2</value>
</attribute>
<attribute>
<name>Author 2</name>
<value>Rob dude 2</value>
</attribute>
</attributes>
<contributors>
<contributor>John 2</contributor>
<contributor>Ryan 2</contributor>
</contributors>
<isbns>
<isbn>
<name>isbn 3</name>
<value>6789a</value>
</isbn>
<isbn>
<name>isbn 4</name>
<value>6789b</value>
</isbn>
</isbns>
</item>
</items>

6

Решение

Согласно вашему расплывчатому вопросу, то, что вы называете «Excel», делает мои слова следующим образом: /items/item Элемент как строка. Исходя из этого в порядке документа, имя-столбца — это имя-тега каждого узла-элемента-листа, если есть повторяющееся имя, позиция будет первой.

Затем он создает по одной строке на строку, но только если все дочерние элементы являются листовыми элементами. В противном случае строка берется за основу для строк из этой строки, а элементы, не содержащие листовых элементов, интерполируются. Например. если такая запись имеет два раза два дополнительных листа с одинаковым именем, они интерполируются в две строки. Их дочерние значения затем помещаются в положение столбцов с именем, соответствующим логике, описанной в первом абзаце.

Насколько глубока эта логика, не ясно из вашего вопроса. Так что я держу это только на этом уровне. В противном случае интерполяция должна будет проходить глубже в дереве. Для этого описанный алгоритм может больше не соответствовать.

Чтобы построить это в PHP, вы можете особенно извлечь выгоду из XPath, и интерполяция творит чудеса как Генератор.

function tree_to_rows(SimpleXMLElement $xml)
{
$columns = [];

foreach ($xml->xpath('/*/*[1]//*[not(*)]') as $leaf) {
$columns[$leaf->getName()] = null;
}

yield array_keys($columns);

$name = $xml->xpath('/*/*[1]')[0]->getName();

foreach ($xml->$name as $source) {
$rowModel       = array_combine(array_keys($columns), array_fill(0, count($columns), null));
$interpolations = [];

foreach ($source as $child) {
if ($child->count()) {
$interpolations[] = $child;
} else {
$rowModel[$child->getName()] = $child;
}
}

if (!$interpolations) {
yield array_values($rowModel);
continue;
}

foreach ($interpolations as $interpolation) {
foreach ($interpolation as $interpolationStep) {
$row = $rowModel;
foreach ($interpolationStep->xpath('(.|.//*)[not(*)]') as $leaf) {
$row[$leaf->getName()] = $leaf;
}
yield array_values($row);
}
}
}
}

Используя это тогда может быть столь же прямым как:

$xml  = simplexml_load_file('items.xml');
$rows = tree_to_rows($xml);
echo new TextTable($rows);

Давать примерный вывод:

+-----+--------+-----+-----------------+----------+-----------+-----+
|sku  |title   |price|name             |value     |contributor|isbn |
+-----+--------+-----+-----------------+----------+-----------+-----+
|abc 1|a book 1|42 1 |Number of pages 1|123 1     |           |12345|
+-----+--------+-----+-----------------+----------+-----------+-----+
|abc 1|a book 1|42 1 |Author 1         |Rob dude 1|           |12345|
+-----+--------+-----+-----------------+----------+-----------+-----+
|abc 1|a book 1|42 1 |                 |          |John 1     |12345|
+-----+--------+-----+-----------------+----------+-----------+-----+
|abc 1|a book 1|42 1 |                 |          |Ryan 1     |12345|
+-----+--------+-----+-----------------+----------+-----------+-----+
|abc 2|a book 2|42 2 |Number of pages 2|123 2     |           |6789 |
+-----+--------+-----+-----------------+----------+-----------+-----+
|abc 2|a book 2|42 2 |Author 2         |Rob dude 2|           |6789 |
+-----+--------+-----+-----------------+----------+-----------+-----+
|abc 2|a book 2|42 2 |                 |          |John 2     |6789 |
+-----+--------+-----+-----------------+----------+-----------+-----+
|abc 2|a book 2|42 2 |                 |          |Ryan 2     |6789 |
+-----+--------+-----+-----------------+----------+-----------+-----+

TextTable это слегка измененная версия от https://gist.github.com/hakre/5734770 позволяя оперировать Генераторы — в случае, если вы ищете этот код.

3

Другие решения

Чтобы получить нужный массив из предоставленного вами XML-файла, вам нужно будет сделать это следующим образом. Это было не слишком весело, поэтому я надеюсь, что это действительно то, что вы хотели.

Учитывая точный XML, который вы дали об этом, вы получите конечный результат.

Это было написано в php 5.6. Я считаю, что вам придется переместить вызовы функций в их собственную строку и заменить [] на array (), если вы столкнетесь с проблемами в вашей среде.

$items = simplexml_load_file("items.xml");

$items_array = [];

foreach($items as $item) {

foreach($item->attributes->attribute as $attribute) {
array_push($items_array, itemsFactory($item, (array) $attribute));
}

foreach((array) $item->contributors->contributor as $contributer) {
array_push($items_array, itemsFactory($item, $contributer));
}

}

function itemsFactory($item, $vars) {

$item = (array) $item;

return [
"sku" => $item['sku'],
"title" => $item['title'],
"price" => $item['price'],
"name" => (is_array($vars) ? $vars['name'] : ""),
"value" => (is_array($vars) ? $vars['name'] : ""),
"contributer" => (is_string($vars) ? $vars : ""),
"isbn" => $item['isbn']
];

}

var_dump($items_array);

Вот результат при запуске вашего XML-файла …

array(8) {
[0]=>
array(7) {
["sku"]=>
string(5) "abc 1"["title"]=>
string(8) "a book 1"["price"]=>
string(4) "42 1"["name"]=>
string(17) "Number of pages 1"["value"]=>
string(17) "Number of pages 1"["contributer"]=>
string(0) ""["isbn"]=>
string(5) "12345"}
[1]=>
array(7) {
["sku"]=>
string(5) "abc 1"["title"]=>
string(8) "a book 1"["price"]=>
string(4) "42 1"["name"]=>
string(8) "Author 1"["value"]=>
string(8) "Author 1"["contributer"]=>
string(0) ""["isbn"]=>
string(5) "12345"}
[2]=>
array(7) {
["sku"]=>
string(5) "abc 1"["title"]=>
string(8) "a book 1"["price"]=>
string(4) "42 1"["name"]=>
string(0) ""["value"]=>
string(0) ""["contributer"]=>
string(6) "John 1"["isbn"]=>
string(5) "12345"}
[3]=>
array(7) {
["sku"]=>
string(5) "abc 1"["title"]=>
string(8) "a book 1"["price"]=>
string(4) "42 1"["name"]=>
string(0) ""["value"]=>
string(0) ""["contributer"]=>
string(6) "Ryan 1"["isbn"]=>
string(5) "12345"}
[4]=>
array(7) {
["sku"]=>
string(5) "abc 2"["title"]=>
string(8) "a book 2"["price"]=>
string(4) "42 2"["name"]=>
string(17) "Number of pages 2"["value"]=>
string(17) "Number of pages 2"["contributer"]=>
string(0) ""["isbn"]=>
string(4) "6789"}
[5]=>
array(7) {
["sku"]=>
string(5) "abc 2"["title"]=>
string(8) "a book 2"["price"]=>
string(4) "42 2"["name"]=>
string(8) "Author 2"["value"]=>
string(8) "Author 2"["contributer"]=>
string(0) ""["isbn"]=>
string(4) "6789"}
[6]=>
array(7) {
["sku"]=>
string(5) "abc 2"["title"]=>
string(8) "a book 2"["price"]=>
string(4) "42 2"["name"]=>
string(0) ""["value"]=>
string(0) ""["contributer"]=>
string(6) "John 2"["isbn"]=>
string(4) "6789"}
[7]=>
array(7) {
["sku"]=>
string(5) "abc 2"["title"]=>
string(8) "a book 2"["price"]=>
string(4) "42 2"["name"]=>
string(0) ""["value"]=>
string(0) ""["contributer"]=>
string(6) "Ryan 2"["isbn"]=>
string(4) "6789"}
}

Если у вас есть доступ к файлу Excel, а не к XML, это может быть намного проще. Если это так, мы можем использовать php excel для рендеринга точно такой же вещи, но это будет работать для любого набора данных, а не только для указанного. Если это не так, я не могу придумать какой-либо другой способ превратить этот XML-файл в то, что вы хотите.

РЕДАКТИРОВАТЬ:

Это также может пролить свет на эту тему и принадлежит самому разработчику PHPExcel. Ошибка фабрики PHPExcel при чтении XML с URL. Как вы можете, я не думаю, что вы в состоянии написать что-то, что могло бы проанализировать любой XML-файл, который вы к нему добавили, не овладев некоторым исходным кодом Excels или не потратив очень много времени на работу над этим .. время, которое много выходит за рамки этого вопроса. Однако, если бы вы написали что-то, что могло бы проанализировать любой XML-файл, у меня было бы ощущение, что это выглядело бы как выше, но с ТОРОМ условных обозначений.

0

Библиотека PHP PHPExcel решает вашу проблему:

https://phpexcel.codeplex.com/

Вы также можете найти некоторые образцы здесь:

https://phpexcel.codeplex.com/wikipage?title=Examples&referringTitle = Home

https://github.com/PHPOffice/PHPExcel/wiki/User%20Documentation

Это самая надежная библиотека Excel для PHP, и она постоянно поддерживается и обновляется.

Имейте в виду, что вы можете читать (из файла Excel и т. д.) и записывать (в файл Excel, PDF и т. д.).

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector