Importing Products from CSV and XML into a Sales System — A Practical Guide
A product import sounds like a one-off formality: drop in a file, click “import,” done. In practice, this is exactly where most of the later mess is born — duplicate items, broken variants, garbled characters instead of accented letters, and stock levels that never quite add up. A good import isn’t a matter of luck; it’s a matter of file preparation and field mapping.
This guide walks through the whole process step by step: how to build a CSV or XML file, how to map columns to system fields, how not to drown in variants and encoding, and how to run incremental updates so an import becomes a repeatable process rather than a one-time shot. At the end — the most common mistakes and how to avoid them.
CSV or XML — which format to choose
Both formats are perfectly fine for importing products, but they have different strengths:
- CSV is a flat table: one row = one product, columns = fields. Simple, lightweight, opens in a spreadsheet, easy to fix by hand. It works well for catalogs with a simple structure, where every product has the same set of fields.
- XML is a nested structure: it naturally describes a product with many variants, multiple images, or attributes with a variable number of values. It’s also often the format suppliers use to expose their feeds.
The practical rule: if your catalog fits sensibly into a flat table, choose CSV — it’s the easiest to control. If you have rich variants and attributes, or you receive a ready-made supplier feed, XML will be more convenient. The format matters less than the quality of the data inside, so don’t get more attached to it than to the tidiness of your columns.
Preparing the file — the foundation of the whole import
Before you import anything, clean up the source. This is the stage that decides success:
- One item = one row (or one node). Don’t glue two products into one line, and don’t split one into several without reason.
- Name column headers unambiguously —
sku,name,price_gross,stock, notcolumn1,price,price2. Clear headers are half the battle when mapping. - Standardize number formats — one decimal separator (dot or comma, consistently), no spaces as thousands separators, prices in a single currency.
- Clean the data — remove trailing spaces, empty rows, and control characters pasted in from another system. Prices and stock must be numbers, not text (“12.00 USD” is text).
- Decide what the key is — in 99% of cases it will be the SKU (more on that below). It determines whether an import creates a new product or updates an existing one.
A good source file explains itself: you look at the headers and you know what’s where. If you have
to guess what field_7 means, the import inherits the same problem.
Field mapping — where the import is really decided
Mapping means assigning the columns of your file to the fields of the sales system. It’s the most important and most underrated step. The minimum set of fields worth mapping:
- SKU — the unique identifier (the import key),
- product name,
- price (unambiguously: gross or net),
- stock level (unit count),
- EAN/GTIN code (if you have one — often needed on marketplaces),
- optionally: description, category, images (URLs), weight, dimensions.
A few rules that save you pain:
- Don’t map “by gut feeling” — check on 2–3 rows that price lands in price, not in stock.
- Decide gross vs. net once and stick to it across the whole file.
- An empty field isn’t always zero — decide whether missing stock means “0 units” or “don’t touch this value.” Those are two completely different intentions.
- Save the mapping as a template if the system allows it — the next import from the same source will then take seconds.
SKUs and variants — the core of a tidy catalog
A SKU (Stock Keeping Unit) is the unique code of a single, sellable item. It’s the shared key the system uses to recognize a product during import, updates, and stock linking across channels. That’s why a SKU must be:
- unique — no two items with the same code,
- stable — once assigned, don’t change it later (changing a SKU = a new product in the system’s eyes),
- consistent across channels — the same product carries the same SKU in the store, in the feed, and in the OMS.
For variants (size, color, capacity), one iron rule applies: each variant is a separate item with its own SKU and its own stock. The “T-shirt” product has no stock — its variants “T-shirt / M / black” and “T-shirt / L / white” do. In CSV you usually lay variants out as separate rows referencing a shared parent product; in XML as nested nodes. If you count stock at the product level instead of the variant level, size M drops to zero while the listing still shows availability — and you sell what you don’t have. We cover counting stock at the right level in the guide to a simple warehouse system for an online store.
Character encoding — the silent killer of accented letters
If after the import you see “łóżko” instead of “łóżko,” that’s an encoding problem. There’s one rule: save and import files in UTF-8.
- When saving CSV from Excel, choose “CSV UTF-8” — the plain “CSV (comma delimited)” often saves in a legacy code page and breaks accented characters.
- In XML keep
<?xml version="1.0" encoding="UTF-8"?>and actually save the file in UTF-8, not just declare it. - Watch for the BOM — an invisible marker at the start of the file can break the first column header. If your first column “won’t catch” during mapping, it’s often the BOM.
- Set the CSV separator — the comma is standard, but some locales default to a semicolon. If everything lands in one column, check the separator first.
Encoding is the single most common cause of an “ugly” import, and also the easiest to avoid — set UTF-8 once and stick with it.
Validation and a sample test — before you let the whole catalog in
Never import 5,000 items blindly. Check the file before it lands in the system for real:
- A trial import of 10–20 rows — look at the result with your own eyes before running the whole thing.
- Validate the keys — missing SKU, duplicate SKUs, and empty names are the most common reasons a row gets rejected.
- Check the types — price and stock must be numbers; “n/a,” “—,” or “12 USD” will break the import.
- Count the rows — the number of items in the file should match the number imported (minus any you deliberately skipped).
- Read the import log — a good system shows which rows passed, which were rejected, and why. That’s your first aid when fixing things.
Ten minutes on a sample import saves hours of cleaning up a catalog where prices landed in the stock field across five thousand items.
Incremental updates — an import is a process, not a one-off
A catalog is alive: prices and stock change, new products arrive. So treat the import as a repeatable process, not a one-time load. The key to that is the incremental update (upsert) keyed on SKU:
- SKU exists → the system updates the existing product (e.g. just price and stock),
- new SKU → the system creates a new product,
- SKU missing from the file → usually left unchanged (unless you deliberately run a full sync).
A good practice is narrower files for frequent changes: a separate, lightweight “SKU + price + stock” feed run often, and a full file with descriptions/images less often. That way the daily stock update is fast and safe, and you replace rich product data only when needed. If the source is a standing supplier feed, it’s worth refreshing it on a schedule instead of uploading it by hand every time.
The most common import mistakes
- Changing a SKU between imports — the system treats the item as new and creates a duplicate.
- Stock counted on the product instead of the variant — a straight path to overselling.
- Price stored as text (“99.00 USD”) — the import rejects the row or reads zero.
- Wrong separator or encoding — the whole file in one column, or garbled accented characters.
- An empty field read as zero — you accidentally wipe stock or prices you didn’t mean to touch.
- Importing everything without a sample test — the error multiplies across thousands of rows before you notice.
How Sellaro handles imports
Sellaro is an OMS (order and product management system) that gathers products and variants from all your connected channels into one normalized view — split into available, low, and out-of-stock, tied together by a shared SKU. The ready-made store modules today are PrestaShop, Sylius, and WooCommerce, and integrations run read-only — Sellaro reads and normalizes data, it doesn’t write back to the store. Allegro and further channels are on the roadmap, and we add a missing integration free of charge as part of your plan.
Sellaro is API-first (API keys, CSV export, search), so products can arrive not only from connected stores but also programmatically — and the automation engine (WHEN→IF→THEN) lets you set up, for example, an email/SMS alert on low stock. The platform is under active development and we say so plainly: some rich-feed import capabilities we extend on request. If you want to understand the category itself, start with the piece on what an OMS for e-commerce is.
Frequently asked questions
Is CSV or XML better for importing products?
For simple catalogs, CSV is more convenient — a flat table, easy to control in a spreadsheet. When you have rich variants and attributes, or you receive a ready-made supplier feed, XML is more natural. More important than the format is data quality and consistent SKUs.
Why do I get garbled characters instead of accented letters after import?
That’s an encoding problem. Save and import files in UTF-8 — in Excel choose “CSV UTF-8,” and in XML make sure the file is actually saved in UTF-8, not just declared as such. Also watch for the invisible BOM marker at the start of the file.
How do I import products with variants?
Treat each variant as a separate item with its own SKU and its own stock. In CSV you usually lay variants out as separate rows referencing a shared parent product; in XML as nested nodes. Count stock at the variant level, never on the aggregate product.
How do I update prices and stock without creating duplicates?
Use an incremental update (upsert) keyed on SKU: an existing SKU updates the product, a new one creates it. Don’t change SKUs once assigned — changing them makes the system see a new item and create a duplicate. For frequent changes, run a narrow “SKU + price + stock” file.
Summary
A good product import from CSV or XML isn’t about one click — it’s about order: a tidy file, deliberate field mapping, consistent and stable SKUs, stock counted at the right level, a file in UTF-8, and validation on a sample before you let the whole thing in. Treat the import as a repeatable, incremental process — a separate lightweight price-and-stock feed, full data only when needed — and you’ll avoid duplicates and a broken catalog.
Want to gather products from all your channels into one normalized view tied together by a shared SKU? See how a simple warehouse system for an online store works, learn what an OMS for e-commerce is, and calculate your cost in Sellaro. We’ll add a missing integration free of charge as part of your plan.