Excel如何读取XML文件?

我已经研究了很多,以同样的方式将xml文件转换为2d数组excel不会像在excel中打开xml文件一样使用相同的algorithm。

<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> 

我想它将它转换为二维数组,就像在Excel中打开相同的文件一样,它会显示给你

在这里输入图像说明


我想像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> 

根据你的模糊的问题,你所谓的“Excel”,它用我自己的话来做以下事情:它把每个/items/item元素作为一行。 从文档顺序中,column-name是每个leaf-element-nodes的标签名称,如果有重复的名称,则位置是第一个。

然后它每行创build一行,但只有所有子元素都是叶元素。 否则,该行被作为该行之外的行的基础,并且包含非叶元素的元素被内插。 例如,如果这样的条目确实有两次具有相同名称的另外两个叶子,则这些叶子被插入两行。 然后将他们的子值按照第一段中描述的逻辑放置到名称列的位置。

这个逻辑究竟有多深不清, 所以我只把它保持在这个水平上。 否则插值将需要深入到树中。 为此,所概括的algorithm可能不再适合。

要在PHP中构build,您可以从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稍微修改的版本,允许&#x5728;Generators上运行 – 以防您正在查找该代码。

为了从xml文件中得到你想要的数组,你必须这样做。 这不是太好玩,所以我希望这确实是你想要的。

鉴于你给出的确切的XML将产生你作为最终结果的输出。

这是用PHP 5.6写的我相信你将不得不将函数调用移动到自己的行,如果遇到环境中的问题,用array()replace[]。

 $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的开发人员在从URL读取XML时出错的 。 正如你可以我不认为你能够写一些东西,可以parsing任何XML文件,而不会得到一些Excels源代码的持有或花了很长时间的工作在这个..时间是多less超出了这个问题的范围。 但是,如果你要写一些能parsing任何XML文件的东西,我觉得它看起来像上面那样,但是有一个TON的条件。

PHP库PHPExcel解决了您的问题:

https://phpexcel.codeplex.com/

你也可以在这里find一些样品:

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

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

这是PHP最可靠的Excel库,它不断的维护和升级。

请记住,您可以读取 (从Excel文件等),并写入 (Excel文件,PDF等)。