Ik converteer op deze manier vele xml bestaden naar csv, dit lukt soms wel en soms niet, terwijl de structuur vrijwel gelijk is.

Nu kom ik er niet meer uit.

Deze functie gebruik ik om een xml bestand om te zetten naar csv



function convertXmlToCsvFile($xml_file_input, $csv_file_output) {
	$xml = simplexml_load_file($xml_file_input);
	
	$output_file = fopen($csv_file_output, 'w');
	
	$header = false;
	
	foreach($xml as $key => $value){
		
		if(!$header) {
			fputcsv($output_file, array_keys(get_object_vars($value),',','"'));
			$header = true;
		}
		fputcsv($output_file, get_object_vars($value),',','"');
		
	}
	
	fclose($output_file);
}



$doen = convertXmlToCsvFile(DOC_ROOT.'shopconnector/feeds/feed'.$_POST['id'].'import.xml',DOC_ROOT.'shopconnector/feeds/feed'.$_POST['id'].'import.csv');



Een xml die wel met de headers (veldnamen) in de xml als eerste regel word opgeslagen is bij deze wel goed:


<?xml version="1.0" encoding="utf-8"?>
<Products>
    <Product>
        <Product_ID>LI64MB520</Product_ID>
        <Product_Name>Siemens iQ100 LI64MB520 Vlakscherm-afzuigkappen - Zilver</Product_Name>
        <Product_URL>https://prf.hn/click/camref:1011l3rad/creativeref:1100l6935/destination:https://www.ao.nl/product/li64mb520-siemens-vlakscherm-afzuigkappen-zilver-39457-4.aspx?&amp;WT.z_PT=MDA&amp;WT.z_AT=Afzuigkappen&amp;WT.z_BR=Siemens&amp;WT.z_FT=Built%20In&amp;WT.z_PC=LI64MB520_GY&amp;WT.z_MT=Affiliate&amp;WT.z_RTM=PHG&amp;WT.srch=1</Product_URL>
        <Image_Thumbnail_URL>http://media.ao.com/productafbeeldingen/klein/li64mb520_gy_siemens_afzuigkap_fr_s.jpg</Image_Thumbnail_URL>
        <Image_Medium_URL>http://media.ao.com/productafbeeldingen/medium/li64mb520_gy_siemens_afzuigkap_fr_m_p.jpg</Image_Medium_URL>
        <Image_Large_URL>http://media.ao.com/productafbeeldingen/groot/li64mb520_gy_siemens_afzuigkap_fr_l.jpg</Image_Large_URL>
        <Price>248.00</Price>
        <Description>Siemens iQ100 LI64MB520 Vlakscherm-afzuigkappen - Zilver</Description>
        <Product_Category>Home &amp; Garden &gt; Kitchen &amp; Dining &gt; Kitchen Appliances &gt; Range Hoods</Product_Category>
        <Product_Type>Afzuigkappen</Product_Type>
        <Category />
        <Sub_Category />
        <SKU>LI64MB520</SKU>
        <Promo_Text />
        <Previous_Price />
        <Warranty>2 Jaren</Warranty>
        <Brand>Siemens</Brand>
        <Availability>In voorraad</Availability>
        <Condition>Neu</Condition>
        <Colour>Zilver</Colour>
        <EAN_Code>4242003717851</EAN_Code>
        <Height>175</Height>
        <Width>598</Width>
        <Depth>290</Depth>
        <Delivery_Cost>0.0000</Delivery_Cost>
      <Company_URL>https://prf.hn/click/camref:1011l3rad/creativeref:1100l6935/destination:http://www.ao.nl</Company_URL>
        <Delivery_Time>2 Werkdagen</Delivery_Time>
        <Energy_Efficiency_Class>B</Energy_Efficiency_Class>
        <Promotions />
        <Manufacturer>BSH</Manufacturer>
        <GTIN_Code>4242003717851</GTIN_Code>
        <Fit_Type>Ingebouwd</Fit_Type>
        <Country>DEU</Country>
        <Additional_ProductInformation />
        <Payment_Method>Maestro – Visa - Visa Debit – Mastercard – Paypal</Payment_Method>
        <Dimensions>(H)17,5 x (B)59,8 x (T)29,0</Dimensions>
        <InStock>True</InStock>
    </Product>


Maar bij deze niet. Bij deze zijn de headers leeg:


<products>
    <product>
        <sku>122470</sku>
        <upc>045496521288</upc>
        <product_name>Mario Kart 7 3DS</product_name>
        <brand>Nintendo</brand>
        <currency>EUR</currency>
        <price>42.99</price>
        <condition>new</condition>
        <product_url>https://prf.hn/click/camref:1100l5eGG/creativeref:1101l32317/destination:https://www.coolblue.nl/product/122470/mario-kart-7-3ds.html</product_url>
        <image_url>https://image.coolblue.nl/1024x1024/products/139591.jpg</image_url>
        <free_shipping>yes</free_shipping>
        <category>Games</category>
        <product_type>Games</product_type>
        <availability>2</availability>
        <shipping_cost>0.00</shipping_cost>
        <group>yes</group>
        <reviewsaveragescore>9.8</reviewsaveragescore>
        <reviewscount>19</reviewscount>
        <coolblueskeuze>0</coolblueskeuze>
        <delivery_time>Voor 23.59 uur besteld, morgen in huis.</delivery_time>
        <categoryid>2053</categoryid>
    </product>



Ik kan er dan niks mee de eerste 4 waarden zijn dan leeg ??

Hoe kan dit? en hoe is dit op te lossen?
Als ik regel 11 wijzig in dit gaat het goed.

fputcsv( $output_file, array_keys( get_object_vars( $value ) ) );
Dit gaat niet goed want, de eerste regels zijn leeg en de headers zijn ook leeg, totaal niet goed dus

[size=xsmall]Toevoeging op 03/04/2019 13:46:30:[/size]

De server gebruikt PHP 7

[size=xsmall]Toevoeging op 03/04/2019 13:51:55:[/size]

Met deze functie leest hij het bestand wel maar haalt alle whitespaces weg, maar laat nog teed niet de node waarden zien als header:


function convertXmlToCsvFile($xml_file_input, $csv_file_output,$innerNode) {

	if (file_exists($xml_file_input)) {
		$xml = simplexml_load_file($xml_file_input);
	$f = fopen($csv_file_output, 'w');
	foreach ($xml->{$innerNode} as $product) {
		
		//echo  $car->getName();
		fputcsv($f, get_object_vars($product),',','"');
		
	}
	fclose($f);
	}
}



De eerste is deze leeg omdat de eerste 4 regels leeg zijn:

$data = fgetcsv($file,null , ''.$r['delimiterr'].'')

De laatste pakt hem wel, maar dan zonder headers

Heeft dit niet gewoon te maken met hoe simple_xml_load_file() het object bouwt, en hoe get_object_vars() hier vervolgens mee omgaat?

Bekijk de verschillende objecten eens met var_dump() ofzo.

Een truuk die geloof ik ook populair is is om het object door een json_encode()/_decode() te halen. Het resultaat is een associatief array die mogelijk wat makkelijker te doorlopen is.

Ook in de user comments van get_object_vars() staan interessante dingen. De PHP-documentatie en de bijbehorende comments bevatten vaak een schat aan informatie.
Ik heb dit geprobeert:


$result = $xml->xpath("//".$waardepost."")[0];

	$arr = json_decode( json_encode($result) , 1);
	foreach ($arr as $key => $waarde) {
		
		echo $key;
		fputcsv($f, $key,',','"');
	}



De key word geprint, maar krijg hem maar niet via fputcsv in de csv, snap niet waarom
Wat zegt in plaats van
<?php echo $key; ?>

<?php var_dump($key); ?>

is dat wel een string?

Als niet, dan zou in plaats van $key in de fput functie misschien (string)$key gebruikt kunnen worden.
Ik denk ook dat je dit probleem kan (en zou moeten) opsplitsen.

Aan de ene kant heb je het uitlezen van een XML (#1).

Aan de andere kant heb je het schrijven naar een CSV (#2).

Dit laatste zou absoluut geen probleem moeten zijn als je hiervoor een normaal associatief array gebruikt.

Dus, waar je voor zou moeten zorgen is dat #1 een fatsoenlijk associatief array uitpoept, zodat het schrijven naar CSV (#2) nooit een probleem vormt.

En wat je dus (enkel) zou moeten uitzoeken is waarom #1 niet het gewenste resultaat oplevert. Hiertoe zou je wat simplexml retourneert nader moeten inspecteren, zoals hiervoven al een aantal keer is aangehaald.

Wat je dus in wezen doet is het standaardiseren van wat je aan het CSV-deel voert, zodat het gedrag van deze data altijd voorspelbaar is (doordat het een standaard format (associatief array) heeft).

Reageren