Parsing XML Feeds from Suppliers for 1C-Bitrix
A supplier's XML feed is a structured file with up-to-date product data: prices, stock, descriptions, characteristics. Unlike Excel price lists, XML is predictable: it has a schema and can be parsed reliably. But "predictable" doesn't mean "standard" — each supplier invents their own XML format.
XML Feed Formats
Several common structures are encountered:
Simple flat XML:
<products>
<product>
<id>12345</id>
<name>Product A</name>
<price>1500.00</price>
<stock>10</stock>
</product>
</products>
Hierarchical with categories:
<catalog>
<categories>
<category id="1" name="Electronics"/>
</categories>
<offers>
<offer id="12345" category_id="1">
<name>Product A</name>
<param name="Color">Black</param>
</offer>
</offers>
</catalog>
With namespaces:
<feed xmlns:g="http://base.google.com/ns/1.0">
<entry>
<g:id>12345</g:id>
<g:price>1500 RUB</g:price>
</entry>
</feed>
Parsing Tools in PHP
SimpleXML — for small files (up to 50 MB):
$xml = simplexml_load_file($filePath);
foreach ($xml->offers->offer as $offer) {
$id = (string)$offer['id'];
$price = (float)$offer->price;
}
XMLReader — for large files (hundreds of thousands of items). Reads file as stream, doesn't load into memory entirely:
$reader = new XMLReader();
$reader->open($filePath);
while ($reader->read()) {
if ($reader->nodeType === XMLReader::ELEMENT && $reader->name === 'offer') {
$node = new SimpleXMLElement($reader->readOuterXml());
// process single element
}
}
For a 500,000-item feed, XMLReader is the only working option. SimpleXML with that size will exhaust PHP memory.
XPath — for navigating complex structures:
$nodes = $xml->xpath('//catalog/offers/offer[@available="true"]');
Attributes and Nested Parameters
Many suppliers store product characteristics as a list of <param> elements:
<offer id="111">
<param name="Brand">Samsung</param>
<param name="Warranty">12 months</param>
<param name="Color">Silver</param>
</offer>
Parsing such parameters:
$params = [];
foreach ($offer->param as $param) {
$name = (string)$param['name'];
$value = (string)$param;
$params[$name] = $value;
}
// $params['Brand'] === 'Samsung'
Then map $params['Brand'] → BRAND property in Bitrix infoblock.
Mapping to Infoblock Properties
Product properties in Bitrix are stored in b_iblock_element_property tables (strings and numbers), b_iblock_element_prop_s{N} (optimized storage). Writing via API:
CIBlockElement::SetPropertyValueCode($elementId, 'BRAND', $params['Brand']);
// or bulk on Add/Update:
'PROPERTY_VALUES' => [
'BRAND' => $params['Brand'],
'WARRANTY' => $params['Warranty'],
]
For list properties (type LIST), value must be ID of list element. If no such value exists — add via CIBlockPropertyEnum::Add().
Synchronization: Update vs. Full Reload
Full reload — simpler. Deactivate all, create/update from feed data, not found remains inactive. Problem: with large catalog (50K+ items) — slow and heavy on database.
Incremental sync — update only changed. Requires comparison with previous state. Approaches:
- Data row hash: if
md5(serialize($currentData)) !== $savedHash— update. -
modifiedfield in feed: update only if change date is newer.
Schedule and Notifications
Feed is processed on schedule via cron. Typical schedule for prices/stock — every 2–4 hours, for descriptions/characteristics — once daily.
0 */3 * * * /usr/bin/php /home/bitrix/www/local/cron/supplier_xml_import.php
After each run — log entry: how many updated, how many errors, execution time. On error (file unavailable, invalid XML) — notification to admin.
Development Timeline
| Option | Scope | Timeline |
|---|---|---|
| Single supplier, simple XML | Parser + price/stock update | 2–3 days |
| Complex XML with params | Mapping characteristics to properties | 3–5 days |
| System for multiple suppliers | Configurable mappings, UI | 6–10 days |







