Php 从包含具有随机数个属性的产品的XML生成产品数据的CSV
我不知道如何正确地将产品数据列表从XML转换为CSV格式 My source是一个XML文件,包含一系列具有颜色、大小、材质等属性的产品,其结构如下:Php 从包含具有随机数个属性的产品的XML生成产品数据的CSV,php,xml,magento,csv,xml-parsing,Php,Xml,Magento,Csv,Xml Parsing,我不知道如何正确地将产品数据列表从XML转换为CSV格式 My source是一个XML文件,包含一系列具有颜色、大小、材质等属性的产品,其结构如下: <?xml version="1.0" encoding="utf-8" ?> <store> <products> <product> <name>T-Shirt</name> <price>
<?xml version="1.0" encoding="utf-8" ?>
<store>
<products>
<product>
<name>T-Shirt</name>
<price>19.00</price>
<attributes>
<attribute>
<name>Color</name>
<options>
<option>
<name>White</name>
<price>0.00</price>
</option>
<option>
<name>Black</name>
<price>0.00</price>
</option>
<option>
<name>Blue</name>
<price>0.00</price>
</option>
</options>
</attribute>
<attribute>
<name>Size</name>
<options>
<option>
<name>XS</name>
<price>-5.00</price>
</option>
<option>
<name>S</name>
<price>-5.00</price>
</option>
<option>
<name>M</name>
<price>0.00</price>
</option>
<option>
<name>L</name>
<price>0.00</price>
</option>
<option>
<name>XL</name>
<price>5.00</price>
</option>
</options>
</attribute>
</attributes>
</product>
<product>
<name>Sweatshirt</name>
<price>49.00</price>
<attributes>
<attribute>
<name>Color</name>
<options>
<option>
<name>White</name>
<price>0.00</price>
</option>
<option>
<name>Black</name>
<price>0.00</price>
</option>
</options>
</attribute>
<attribute>
<name>Size</name>
<options>
<option>
<name>XS</name>
<price>-10.00</price>
</option>
<option>
<name>M</name>
<price>0.00</price>
</option>
<option>
<name>XL</name>
<price>10.00</price>
</option>
</options>
</attribute>
<attribute>
<name>Material</name>
<options>
<option>
<name>Cotton</name>
<price>10.00</price>
</option>
<option>
<name>Polyester</name>
<price>0.00</price>
</option>
</options>
</attribute>
</attributes>
</product>
<product>
<name>Earrings</name>
<price>29.00</price>
</product>
</products>
</store>
我已经设法为简单的产品(如耳环和只有一个属性的产品)生成CSV输出,但我正在努力找到一种方法来为具有多个属性的产品生成所有可能的产品属性组合
到目前为止,我在这方面的痛苦尝试产生了以下代码:
<?php
mb_internal_encoding("UTF-8");
header('Content-Type: text/html; charset=utf-8');
$source = "example.xml";
$handle = fopen($source, "r");
$fp = fopen('export.csv', 'w');
$xml = simplexml_load_file($source);
// Generate list of attributes (for csv header etc.)
$header_attributes = array();
foreach ($xml->products->product as $product) {
if(isset($product->attributes)) {
foreach($product->attributes->attribute as $attribute) {
array_push($header_attributes, $attribute->name);
}
}
}
$header_attributes = array_unique($header_attributes);
$csvheader = array(
'name','price' // these exist for all products, could also include weight, image, description, special price etc...
);
$static_csvheadercount = count($csvheader);
foreach($header_attributes as $attribute) {
array_push($csvheader, $attribute); // add variable number of attribute fields to csv header
}
fputcsv($fp, $csvheader);
foreach ($xml->products->product as $product) { // loop through each product
if(isset($product->attributes)) $simple = 0;
else $simple = 1;
if($simple == 1) { // if product is a simple product with no attributes
$output=array();
array_push($output,(string)$product->name);
array_push($output,(string)$product->price);
for($i = $static_csvheadercount + $attribute_position; $i < count($csvheader); $i++) {
array_push($output, '');
}
fputcsv($fp, $output);
}
else { // is a configurable product with attributes
$json = json_encode($product->attributes);
$attributes = json_decode($json, TRUE);
$attributes_number = count($product->attributes->attribute);
if($attributes_number > 1) { // if product has more than 1 attributes so we have to generate each attribute combination
//
// I'm trying to figure out what should happen here
//
}
else { // if product has only one attribute
$attributename = (string)$product->attributes->attribute->name;
$attribute_position = array_search($attributename, $header_attributes);
$options_number = count($product->attributes->options->option);
$pos = 1;
foreach($attributes['attribute']['options']['option'] as $option) {
$output=array();
array_push($output,(string)$product->name);
array_push($output,(string)$product->price);
for($i = $static_csvheadercount - 1; $i < ($static_csvheadercount + $attribute_position); $i++) {
array_push($output, '');
}
$output[$static_csvheadercount + $attribute_position] = $option['name'];
for($i = $static_csvheadercount + $attribute_position; $i < count($csvheader) - 1 ; $i++) {
array_push($output, '');
}
fputcsv($fp, $output);
$pos++;
}
$output=array();
array_push($output,(string)$product->name);
array_push($output,(string)$product->price);
for($i = $static_csvheadercount; $i < count($csvheader); $i++) {
array_push($output, '');
}
fputcsv($fp, $output);
}
}
}
?>
以下是有用的链接:
或
如果没有帮助的话。
在每个属性中都有x个选项。例如,您有2种颜色和3种尺寸选项。因此,总共有2x3=6个产品。
使用first for cycle,您可以计算最终将拥有多少产品以及将拥有多少属性。因此,您可以定义产品的外观。例如:
$products = array();
$product = array("size"=>,"color"=>); total 2 attributes
$products[] = $product;
这意味着您的每种产品都有两个属性。
因此,您应该跳过所有属性选项并收集产品的所有可能变体。因此,理想情况下,通过这个简单的解决方案,您可能会得到如下结果:
尺寸:XS S或12
颜色:红蓝格伦或3 4 5那么我们会有这样的东西:
$products = array();
$product = array("size"=>,"color"=>); total 2 attributes
$products[] = $product;
3 4 5 3 4 5
1 2 1 2 1 2
也许我的解决方案不是最好的。我甚至不知道它是否有效。但是你可以得到一些有用的信息
$variant_count = 1;
$opts = array();
for($attributes->attribute as $attr){
$variant_count *= count($attr->option);
$opts[] = $attr->option;
}
$products = array();
for($i = 0; $i < $variant_count; $i++){
$product = array();
for($x = 0; $x < count($opts); $x++){
$y = $i...;// here should be some function which counts proper $y
$product[$x] = $opts[$x][$y];
}
}
$variant\u count=1;
$opts=array();
对于($attributes->attributes as$attr){
$variant_count*=计数($attr->option);
$opts[]=$attr->option;
}
$products=array();
对于($i=0;$i<$variant\u count;$i++){
$product=array();
对于($x=0;$x
在xsl中非常简单,这里有一个xsl可以满足您的需要
只是两个XSL技巧需要考虑。
- 输出框返回此值
- 将输出方法设置为文本,不进行索引
祝你好运
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text" indent="no"/>
<xsl:template match="/">
<xsl:for-each select='store/products/product'>
<!-- Store off the current product name and price -->
<xsl:variable name='name' select='name'/>
<xsl:variable name='price' select='price'/>
<!-- Store off the material, colors and sizes-->
<xsl:variable name='materials' select='attributes/attribute[name="Material"]/options/option/name'/>
<xsl:variable name='colors' select='attributes/attribute[name="Color"]/options/option/name'/>
<xsl:variable name='sizes' select='attributes/attribute[name="Size"]/options/option/name'/>
<!-- If no colors (earrings), jump ahead -->
<xsl:if test='$colors'>
<!-- Iterate the colors -->
<xsl:for-each select='$colors'>
<!-- Store off the current color -->
<xsl:variable name='color' select='.'/>
<!-- Iterate the sizes -->
<xsl:for-each select='$sizes'>
<xsl:variable name='size' select='.'/>
<!-- If materials, iterate through them too -->
<xsl:if test='$materials'>
<xsl:for-each select='$materials'>
<xsl:variable name='material' select='.'/>
<xsl:value-of select='$name'/>,<xsl:value-of select='$price'/>,<xsl:value-of select='$color'/>,<xsl:value-of select='$size'/>,<xsl:value-of select='$material'/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:if>
<!-- If not materials, output what we've got -->
<xsl:if test='not($materials)'>
<xsl:value-of select='$name'/>,<xsl:value-of select='$price'/>,<xsl:value-of select='$color'/>,<xsl:value-of select='$size'/>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:if>
<xsl:if test='not($colors)'>
<xsl:value-of select='$name'/>,<xsl:value-of select='$price'/>,,,
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
,,,,
;
,,,
;
,,,,
;
如果您不知道如何使用XSL,这里有一个快速的小脚本来帮助您入门
<?php
try {
$xml = new DOMDocument();
$strFileName = "att.xml";
$xml->load($strFileName);
$xsl = new DOMDocument();
$strFileName = "att.xsl";
$xsl->load($strFileName);
$proc = new XSLTProcessor();
$proc->importStylesheet($xsl);
echo $proc->transformToXML($xml);
} catch( Exception $e ) {
echo $e->getMessage();
}
?>