# XML Record Batcher — Large XML to NDJSON (`creatieve_naald/xml-record-batcher`) Actor

Split plain XML uploads into ordered NDJSON batches of at most 1 MiB. Up to 200 MiB and 100,000 records per document. Keep attributes, namespaces and mixed content. $0.10 per successful document; no external feed fetching.

- **URL**: https://apify.com/creatieve_naald/xml-record-batcher.md
- **Developed by:** [Stefan Schellen](https://apify.com/creatieve_naald) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$100.00 / 1,000 prepared xml documents

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## XML Record Batcher

Prepare a large XML upload as small, ordered NDJSON files for a workflow that cannot hold the whole converted document in memory. Choose an exact record tag; retrieve the manifest, then fetch and process **one batch at a time**.

This is a paid Agent Tools utility. Price: $0.10 per successfully prepared XML document, including all batches. Platform usage is included in the event price.

### Example

Input:

```json
{"xmlText":"<feed><item id=\"01\">First</item><item id=\"02\">Second</item></feed>","recordTag":"item"}
```

A batch contains one JSON object per line:

```json
{"index":1,"element":{"tag":"item","attributes":{"id":"01"},"content":["First"]}}
{"index":2,"element":{"tag":"item","attributes":{"id":"02"},"content":["Second"]}}
```

Attributes and text remain strings; repeated children and mixed text/child order are preserved. Namespace names expand to `URI|local`, for example `urn:catalog|item`. Nested matching tags remain within the selected outer record. Comments and processing instructions are omitted. This is structured XML, **not** automatic product-field mapping, XPath, schema validation or business-data cleanup.

### Larger input

Clear the inline example before using `xmlFiles`. Supply exactly one **accessible Apify key-value-store record URL** for plain XML. For private storage, obtain a record-specific signed URL using your Apify client’s `get_record_public_url` method; never put your account token in a URL. Simple record keys only (letters, digits, `_-.~`); rename other keys before using them. External URLs, redirects, ZIP and gzip are not supported. Your workflow must get the original document into Apify storage first. This does not solve source-server compression or download restrictions.

The native upload widget has been removed: a normal private Console upload link does not include access authorization, and this Actor never forwards account credentials to downloads. Use a signed record link for large files; for XML up to 1 MiB, paste the text into `xmlText`. This change does not add external feed fetching or broader account access.

For Python SDK users, after uploading `source.xml` into your own store:

```python
signed_url = client.key_value_store(store_id).get_record_public_url("source.xml")
run_input = {"xmlFiles": [signed_url], "recordTag": "item"}
```

Keep the signed URL private. Start the Actor separately with your chosen spending limit, wait for success, then use the [free validated batch reader and guide](https://github.com/AI-AgentTools/workflow-examples/blob/main/XML_GUIDE.txt). The reader never starts a new Actor run. The private cloud acceptance tested signed input; the reader's authenticated HTTP integration remains untested.

### Output and limits

The single dataset row and `OUTPUT` key contain record count, source/output byte counts and ordered batch entries: `recordKey`, `bytes`, `records`, `sha256`. Files live in the run's default key-value store. Fetch a record using your Apify credentials; do not assume the key alone is a public link. Parse each NDJSON line separately and release the batch before fetching the next.

- Plain XML: at most 200 MiB; inline input: 1 MiB.
- Up to 100,000 selected records; depth at most 64.
- Each serialized record and each batch: at most 1 MiB; total output at most 220 MiB.
- DTDs and entity declarations are rejected. XML must validate to its end before upload starts. No partial success for malformed or over-limit XML.
- Parser child has Linux memory/CPU limits and a wall-clock timeout. These controls are not a security audit or a claim to support every XML dialect.
- Failed upload may leave partial batch records in run storage: use only a successful run with a complete manifest. Inspect the existing run before retrying; a timeout does not prove the run failed.

### Workflow and alternatives

Start the Actor asynchronously, wait for success, read its manifest and loop over batch keys. An n8n Code step can split a downloaded batch by newline and parse each line with `JSON.parse`. This is guidance, not a verified n8n Cloud template. Keep tokens in credentials, not exported workflows. Original input and output consume your Apify storage; manage retention appropriate to your data.

Free alternatives are Python's XML parsers with a staging writer, a self-hosted worker, or n8n's XML node for documents that fit its memory. A generic XML-to-JSON converter is simpler for small complete documents. This tool is useful when you want hosted bounded batches without maintaining that worker.

### Tested scope

Local synthetic fixtures cover order, repeated children, namespaces, mixed content, malformed XML, DTD rejection, limits, batch integrity and billing orchestration. A local 184.6 MB synthetic input yielded 90,000 records; this is not an n8n/cloud performance guarantee. Private cloud acceptance processed the same 90,000-record fixture into 184 batches. Manifest totals and first/middle/last batch hashes were checked; every output byte was not downloaded again. Actual n8n Cloud execution has not been tested. No customer documents or external feeds were used.

Report reproducible problems through Apify Issues using synthetic data. Remove credentials and signed links. No custom integration or schema mapping service. Built with AI assistance. More tools: https://apify.com/creatieve_naald

# Actor input Schema

## `xmlText` (type: `string`):

Inline XML up to 1 MiB. Clear this field before supplying xmlFiles.

## `xmlFiles` (type: `array`):

One existing readable Apify KVS record URL, up to 200 MiB. For private storage obtain a record-specific signed URL with your SDK. Ordinary unsigned private Console upload links are not supported. No account tokens, external hosts, ZIP or gzip. Clear xmlText first.

## `recordTag` (type: `string`):

Exact tag. Namespace example: urn:catalog|item. Matching nested tags remain inside the outer selected record.

## Actor input object example

```json
{
  "xmlText": "<feed><item id=\"01\">First</item><item id=\"02\">Second</item></feed>",
  "recordTag": "item"
}
```

# Actor output Schema

## `result` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "xmlText": "<feed><item id=\"01\">First</item><item id=\"02\">Second</item></feed>"
};

// Run the Actor and wait for it to finish
const run = await client.actor("creatieve_naald/xml-record-batcher").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "xmlText": "<feed><item id=\"01\">First</item><item id=\"02\">Second</item></feed>" }

# Run the Actor and wait for it to finish
run = client.actor("creatieve_naald/xml-record-batcher").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "xmlText": "<feed><item id=\\"01\\">First</item><item id=\\"02\\">Second</item></feed>"
}' |
apify call creatieve_naald/xml-record-batcher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,creatieve_naald/xml-record-batcher"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/iLm02Ogdc0Gqe0ByV/builds/oaK5pPYHwKiQoypYa/openapi.json
