0

I'm somewhat stuck on a problem. I'm attempting to write an app that basically reads and sorts DATA from an online XML file containing customers and recreates those customers in Wordpress/woocommerce through cURL/php/JSON. I'm using insomnia to test my calls and code pieces.

This is what I got so far:

  1. Pull customer data from the online database into xml [ but its raw unsorted and too much info ]
  2. Create a customer in Woocommerce/ Wordpress by POST request in JSON/PHP/cURL

Im currently missing the bridge between sorting the XML data into a table and having that data be filled into a piece of code containing variables that recreates said data into woocommerce through REST API.


Shortly said, I want to:

  1. Pull Customer data into XML - OK

  2. Read the XML customer data and assign it to variables

  3. Use said variables to push and recreate customers in Woocommerce/wordpress.

How should I approach this ?

This is how I create a customer in woocommerce. Basically the CURL_POSTFIELDS tags should contain a single line from that customer XML table with its assign data.

<?php

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://www.testsite.com/wp-json/wc/v3/customers?consumer_key=XXXXXXXXXXXX&consumer_secret=XXXXXXXXXXXXXXXXX",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{\n  \"email\": \"[email protected]\",\n  \"first_name\": \"John\",\n  \"last_name\": \"Doe\",\n  \"username\": \"john.doe\",\n  \"billing\": {\n    \"first_name\": \"John\",\n    \"last_name\": \"Doe\",\n    \"company\": \"\",\n    \"address_1\": \"969 Market\",\n    \"address_2\": \"\",\n    \"city\": \"San Francisco\",\n    \"state\": \"CA\",\n    \"postcode\": \"94103\",\n    \"country\": \"US\",\n    \"email\": \"[email protected]\",\n    \"phone\": \"(555) 555-5555\"\n  },\n  \"shipping\": {\n    \"first_name\": \"John\",\n    \"last_name\": \"Doe\",\n    \"company\": \"\",\n    \"address_1\": \"969 Market\",\n    \"address_2\": \"\",\n    \"city\": \"San Francisco\",\n    \"state\": \"CA\",\n    \"postcode\": \"94103\",\n    \"country\": \"US\"\n  }\n}",
  CURLOPT_HTTPHEADER => [
    "Authorization: Basic Og==",
    "Content-Type: application/json"
  ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

The JSON in insomania has these as input, same story as above, it should be filled with the customer data form the XML:

{
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "username": "john.doe",
  "billing": {
    "first_name": "John",
    "last_name": "Doe",
    "company": "",
    "address_1": "969 Market",
    "address_2": "",
    "city": "San Francisco",
    "state": "CA",
    "postcode": "94103",
    "country": "US",
    "email": "[email protected]",
    "phone": "(555) 555-5555"
  },
  "shipping": {
    "first_name": "John",
    "last_name": "Doe",
    "company": "",
    "address_1": "969 Market",
    "address_2": "",
    "city": "San Francisco",
    "state": "CA",
    "postcode": "94103",
    "country": "US"
  }
}

Here is a sample of the response from the XML data. I've expanded account code 2 to show its contents. Obviously I don't want everything from it, I'm only interested in name, email, address, phone and VAT number for instance.

<eExact
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="eExact-XML.xsd">
  <Accounts>
    <Account code="0" searchcode="" status="A" ID="{2723dc8f-33d0-XXXX-9710-XXXXXXXXXXXX}">
        </Account>
    <Account code="1" searchcode="" status="A" ID="{7c6f362c-79e1-XXXX-8822-XXXXXXXXXXXX}">
        </Account>
    <Account code="2" searchcode="" status="C" ID="{132c9c6b-dd66-XXXX-b276-XXXXXXXXXXXX}">
      <Name>BOB</Name>
      <Phone>6845641564564654156454</Phone>
      <PhoneExt />
      <Fax />
      <Email>[email protected]</Email>
      <HomePage>example.com<</HomePage>
      <Language code="EN" />
      <IsSupplier>1</IsSupplier>
      <CanDropShip>0</CanDropShip>
      <IsBlocked>0</IsBlocked>
      <IsReseller>0</IsReseller>
      <IsSales>1</IsSales>
      <IsPurchase>1</IsPurchase>
      <ShowRemarkForSales>0</ShowRemarkForSales>
      <Contact number="2090075" gender="M" default="1" ID="{2449ce5d-41b3-XXXX-bab3-XXXXXXXXXXXX}">
        <LastName>BOB</LastName>
        <MiddleName />
        <BirthName>BOB</BirthName>
        <BirthNamePrefix />
        <PartnerName />
        <PartnerNamePrefix />
        <FirstName>BOB</FirstName>
        <Initials />
        <Language code="SAMPLE" />
        <Phone>44546456456e</Phone>
        <PhoneExt />
        <Fax />
        <Mobile>eeeeeeeeeeeeeee</Mobile>
        <Email>[email protected]</Email>
        <BirthPlace />
        <IsMailingExcluded>0</IsMailingExcluded>
        <Job>
          <Description>role</Description>
        </Job>
        <IsAnonymised>0</IsAnonymised>
      </Contact>
      <Address type="TES" default="1" ID="{41bde841-afde-XXXX-9cd0-XXXXXXXXXXXX}">
        <AddressLine1>sampleroad</AddressLine1>
        <AddressLine2 />
        <AddressLine3 />
        <PostalCode>1000000</PostalCode>
        <City>Appels</City>
        <State code="O-V" />
        <Country code="EN" />
        <Phone />
        <Fax />
        <Contact number="2090075" ID="{2449ce5d-41b3-XXXX-bab3-XXXXXXXXXXXX}" />
      </Address>
      <VATNumber>VATXXXXXXXX</VATNumber>
      <VATLiability>L</VATLiability>
      <GovernmentVATSystem>0</GovernmentVATSystem>
      <ChamberOfCommerce />
      <ChamberOfCommerceEstablishment />
      <GlnNumber />
      <SalesCurrency code="EUR" />
      <PurchaseCurrency code="EUR" />
      <CreditLine>
        <Sales>0</Sales>
        <Purchase>0</Purchase>
      </CreditLine>
      <Discount>
        <SalesPercentage>0.9</SalesPercentage>
        <PurchasePercentage>0</PurchasePercentage>
      </Discount>
      <AccountClassifications />
      <IsMailing>0</IsMailing>
      <IsCompetitor>0</IsCompetitor>
      <StartDate>2020-11-25</StartDate>
      <IntraStat>
        <System />
        <TransactionA />
        <TransactionB />
        <TransportMethod />
        <DeliveryTerm />
        <Area />
      </IntraStat>
      <InvoicingMethod>0</InvoicingMethod>
      <IsAnonymised>0</IsAnonymised>
    </Account>
  </Accounts>
  <Topics>
    <Topic code="Accounts" ts_d="XXXXXXXXXXXX" count="3" pagesize="1000" />
  </Topics>
  <Messages />
</eExact>
4
  • 1
    Parse the XML to an object, and then encode the object to JSON. Have you tried anything specific? Commented Dec 14, 2020 at 15:06
  • P.S. "Pull customer data from the online database into xml"...does it have to be XML? Does that database not output anything else? e.g. could it return JSON directly? Just putting that out there in case the process could be simplified, but obviously I don't know anything about that system and what access you have or what you can get from it. Commented Dec 14, 2020 at 15:08
  • @ADyson, it can export as .csv aswell but i reckon thats even harder to work with than xml... Haven't tried anything specific yet. Commented Dec 14, 2020 at 15:34
  • 1
    It's probably harder if you have a nested data structure, which it looks like you have..so yeah maybe stick to XML. You should be able to find tutorials etc already which explain how to parse XML using PHP. Give it a try. If you then get stuck, ask us something more specific. Commented Dec 14, 2020 at 15:48

1 Answer 1

2

Build an array structure from the XML using DOM+Xpath and serialize it to JSON. Xpath expressions allow you to fetch node list and scalar values from the DOM using location paths and conditions.

For example:

  • any Account
    /eExact/Accounts/Account
  • that has the status C
    /eExact/Accounts/Account[@status="C"]
  • just the last node
    (/eExact/Accounts/Account[@status="C"])[last()]

The / at the start of the location path anchors it to the document otherwise the expression will use the current context (the second argument of DOMXpath::evaluate()).

For example:

  • any Email child element
    Email
  • cast first found Email to string
    string(Email)

Demo:

$document = new DOMDocument();
$document->loadXML(getXML());
$xpath = new DOMxpath($document);

$json = [];
foreach ($xpath->evaluate('(/eExact/Accounts/Account[@status="C"])[last()]') as $account) {
    $json['email'] = $xpath->evaluate('string(Email)', $account);
    $json['username'] = $xpath->evaluate('string(Name)', $account);
    $json['first_name'] = $xpath->evaluate('string(Contact[@default="1"]/FirstName)', $account);
    $json['last_name'] = $xpath->evaluate('string(Contact[@default="1"]/LastName)', $account);
    $json['billing'] = [
      'first_name' => $xpath->evaluate('string(Contact[@default="1"]/FirstName)', $account),
      'last_name' => $xpath->evaluate('string(Contact[@default="1"]/LastName)', $account),
      'postcode'=> $xpath->evaluate('string(Address[@default="1"]/PostalCode)', $account),
    ];
    // ...
}
echo json_encode($json, JSON_PRETTY_PRINT);

Output:

{
    "email": "[email protected]",
    "username": "BOB",
    "first_name": "BOB",
    "last_name": "BOB",
    "billing": {
        "first_name": "BOB",
        "last_name": "BOB",
        "postcode": "1000000"
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Getting: PHP Fatal error: Uncaught Error: Call to undefined function getXML(), is this because something else needs to be defined/initiated in the code or is this a config problem in xamp. Im using xampp on windows to run the php code.
Figured it out. Had to replace the getXML function with my $response parameter since thats where my xml is the output

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.