XML omzetten naar CSV verdwijnt de header soms

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Daniel van Seggelen

Daniel van Seggelen

03/04/2019 10:49:48
Quote Anchor link
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

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<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?
 
PHP hulp

PHP hulp

22/04/2019 23:02:06
Honeypot
 
Adoptive Solution

Adoptive Solution

03/04/2019 12:10:24
Quote Anchor link
Als ik regel 11 wijzig in dit gaat het goed.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
fputcsv( $output_file, array_keys( get_object_vars( $value ) ) );
 
Daniel van Seggelen

Daniel van Seggelen

03/04/2019 13:42:18
Quote Anchor link
Dit gaat niet goed want, de eerste regels zijn leeg en de headers zijn ook leeg, totaal niet goed dus

Toevoeging op 03/04/2019 13:46:30:

De server gebruikt PHP 7

Toevoeging op 03/04/2019 13:51:55:

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

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
 
Thomas van den Heuvel

Thomas van den Heuvel

03/04/2019 16:22:41
Quote Anchor link
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.
 
Daniel van Seggelen

Daniel van Seggelen

03/04/2019 23:28:05
Quote Anchor link
Ik heb dit geprobeert:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
$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
 
Ivo P

Ivo P

04/04/2019 09:28:50
Quote Anchor link
Wat zegt in plaats van
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php echo $key; ?>


Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?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.
 
Thomas van den Heuvel

Thomas van den Heuvel

04/04/2019 16:20:19
Quote Anchor link
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).
Gewijzigd op 04/04/2019 16:25:30 door Thomas van den Heuvel
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.