---
source: https://carbone.io/documentation/design/template-formats/xml.html
title: "XML Templates | Generate XML Files from JSON | Carbone"
description: "Generate XML files from XML templates and JSON with the Carbone API: e-invoices, SEPA payments, sitemaps and product feeds, with loops, totals and escaping."
generated_at: "2026-11-11"
---

# XML templates

Write an XML file with Carbone tags, and generate e-invoices, payment files and product feeds from JSON data.  
COMMUNITY FEATURE Available for:  
✓ Carbone Cloud  
✓ Carbone On-premise  
✓ Embedded Carbone JS   v2.0+ 

Any XML file can be a template. Write Carbone tags in element text and attribute values, send your JSON data to the API, and get back an XML file with the structure of the template, ready for a bank, a tax platform or a marketplace.

## Basic

Write a tag where a value goes, in the text of an element or in an attribute value. In `{d.recipient.name}`, `d` is the root of the data and `recipient.name` is the path to the value. Carbone replaces only the tags: the XML declaration, the namespaces and their prefixes, the comments and the indentation stay as written.

**Data** ([basic-data.json](/file/xml/basic-data.json)):

```json
{
  "reference": "SHP-2026-10482",
  "shipDate": "2026-11-12",
  "service": "EXPRESS",
  "shipper": {
    "name": "Acme Corporation",
    "city": "Chicago",
    "country": "US"
  },
  "recipient": {
    "name": "Vandelay & Sons Industries",
    "street": "18 Mill Lane",
    "postalCode": "02108",
    "city": "Boston",
    "country": "US",
    "email": "receiving@vandelay.example"
  },
  "package": {
    "weight": 4.2,
    "contents": "Cordless drills with batteries <100 Wh"
  },
  "instructions": "Use the loading dock & call 10 min before"
}
```

**Template** ([basic-template.xml](/file/xml/basic-template.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ShipmentRequest xmlns="urn:acme:shipping:2.0" version="2.0">
  <Reference>{d.reference}</Reference>
  <ShipDate>{d.shipDate}</ShipDate>
  <Service code="{d.service}"/>
  <Shipper>
    <Name>{d.shipper.name}</Name>
    <City>{d.shipper.city}</City>
    <Country>{d.shipper.country}</Country>
  </Shipper>
  <Recipient>
    <Name>{d.recipient.name}</Name>
    <Street>{d.recipient.street}</Street>
    <City postalCode="{d.recipient.postalCode}">{d.recipient.city}</City>
    <Country>{d.recipient.country}</Country>
    <Email>{d.recipient.email}</Email>
  </Recipient>
  <Package weight="{d.package.weight}" unit="kg">
    <Contents>{d.package.contents}</Contents>
  </Package>
  <Instructions>{d.instructions}</Instructions>
</ShipmentRequest>
```

**Result** ([basic-report.xml](/file/xml/basic-report.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ShipmentRequest xmlns="urn:acme:shipping:2.0" version="2.0">
  <Reference>SHP-2026-10482</Reference>
  <ShipDate>2026-11-12</ShipDate>
  <Service code="EXPRESS"/>
  <Shipper>
    <Name>Acme Corporation</Name>
    <City>Chicago</City>
    <Country>US</Country>
  </Shipper>
  <Recipient>
    <Name>Vandelay &amp; Sons Industries</Name>
    <Street>18 Mill Lane</Street>
    <City postalCode="02108">Boston</City>
    <Country>US</Country>
    <Email>receiving@vandelay.example</Email>
  </Recipient>
  <Package weight="4.2" unit="kg">
    <Contents>Cordless drills with batteries &lt;100 Wh</Contents>
  </Package>
  <Instructions>Use the loading dock &amp; call 10 min before</Instructions>
</ShipmentRequest>
```

-   Carbone escapes `&`, `<` and `>` in the values, like the recipient name and the contents. For free text in an attribute, see [attributes](#best-practices).
-   A missing or empty value prints an empty element, like `<Note></Note>`. To remove the element instead, use a [condition](#conditions).
-   Tags in XML comments are replaced too.

Learn more about [tags](/documentation/design/substitutions/the-basics.md).

## Loops

A loop repeats an element for each item of an array. The template needs two elements:

-   **The element to repeat**, with `[i]` in its tags: `{d.pages[i].url}`.
-   **The next element**, with `[i+1]` in one tag: `{d.pages[i+1].url}`. It marks the end of the loop and is removed from the report.

Carbone repeats the element with its children and attributes. Add a condition to the `[i+1]` tag to filter the items: `noindex=false` leaves the cart page out of this sitemap.

**Data** ([loops-data.json](/file/xml/loops-data.json)):

```json
{
  "pages": [
    { "url": "https://www.acme.example/", "updatedAt": "2026-11-10T08:15:00Z", "changefreq": "daily", "priority": 1, "noindex": false },
    { "url": "https://www.acme.example/products/cordless-drill", "updatedAt": "2026-11-04T14:30:00Z", "changefreq": "weekly", "priority": 0.8, "noindex": false },
    { "url": "https://www.acme.example/products?category=tools&sort=new", "updatedAt": "2026-11-09T06:00:00Z", "changefreq": "daily", "priority": 0.6, "noindex": false },
    { "url": "https://www.acme.example/cart", "updatedAt": "2026-11-10T09:00:00Z", "changefreq": "always", "priority": 0.1, "noindex": true },
    { "url": "https://www.acme.example/support/warranty", "updatedAt": "2026-09-22T10:00:00Z", "changefreq": "monthly", "priority": 0.5, "noindex": false }
  ]
}
```

**Template** ([loops-template.xml](/file/xml/loops-template.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>{d.pages[i].url}</loc>
    <lastmod>{d.pages[i].updatedAt:formatD('YYYY-MM-DD')}</lastmod>
    <changefreq>{d.pages[i].changefreq}</changefreq>
    <priority>{d.pages[i].priority}</priority>
  </url>
  <url>
    <loc>{d.pages[i+1, noindex=false].url}</loc>
  </url>
</urlset>
```

**Result** ([loops-report.xml](/file/xml/loops-report.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://www.acme.example/</loc>
    <lastmod>2026-11-10</lastmod>
    <changefreq>daily</changefreq>
    <priority>1</priority>
  </url>
  <url>
    <loc>https://www.acme.example/products/cordless-drill</loc>
    <lastmod>2026-11-04</lastmod>
    <changefreq>weekly</changefreq>
    <priority>0.8</priority>
  </url>
  <url>
    <loc>https://www.acme.example/products?category=tools&amp;sort=new</loc>
    <lastmod>2026-11-09</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.6</priority>
  </url>
  <url>
    <loc>https://www.acme.example/support/warranty</loc>
    <lastmod>2026-09-22</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.5</priority>
  </url>
  
</urlset>
```

Learn more about [loops](/documentation/design/repetitions/with-arrays.md), [filtering](/documentation/design/repetitions/filtering.md) and [sorting](/documentation/design/repetitions/sorting.md).

### Nested loops

A loop can contain another loop. In this SEPA credit transfer file (pain.001.001.09), `{d.batches[i].id}` repeats the payment block `PmtInf` for each execution date, and `{d.batches[i].payments[i].name}` repeats the transaction `CdtTrfTxInf` for each payment of the block. The `PmtInf` element with `[i+1]` closes the outer loop.

Aggregators fill the control sums: `:aggCount` counts the transactions and `:aggSum` adds their amounts, for the whole file in the group header, and for each block inside the loop.

**Data** ([nested-data.json](/file/xml/nested-data.json)):

```json
{
  "messageId": "ACME-SCT-20261110-01",
  "createdAt": "2026-11-10T08:30:00Z",
  "debtor": {
    "name": "Acme Corporation",
    "iban": "FR7630006000011234567890189"
  },
  "batches": [
    {
      "id": "BATCH-20261112",
      "executionDate": "2026-11-12",
      "payments": [
        { "invoice": "INV-88412", "amount": 1249.99, "name": "Globex GmbH", "iban": "DE89370400440532013000" },
        { "invoice": "INV-88419", "amount": 860.25, "name": "Initech B.V.", "iban": "NL91ABNA0417164300" }
      ]
    },
    {
      "id": "BATCH-20261115",
      "executionDate": "2026-11-15",
      "payments": [
        { "invoice": "INV-88433", "amount": 3420.17, "name": "Umbrella Logistica S.L.", "iban": "ES9121000418450200051332" }
      ]
    }
  ]
}
```

**Template** ([nested-template.xml](/file/xml/nested-template.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>{d.messageId}</MsgId>
      <CreDtTm>{d.createdAt:formatD('YYYY-MM-DDTHH:mm:ssZ')}</CreDtTm>
      <NbOfTxs>{d.batches[].payments[].amount:aggCount}</NbOfTxs>
      <CtrlSum>{d.batches[].payments[].amount:aggSum:round(2)}</CtrlSum>
      <InitgPty><Nm>{d.debtor.name}</Nm></InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>{d.batches[i].id}</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <NbOfTxs>{d.batches[i].payments[].amount:aggCount}</NbOfTxs>
      <CtrlSum>{d.batches[i].payments[].amount:aggSum:round(2)}</CtrlSum>
      <PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf>
      <ReqdExctnDt><Dt>{d.batches[i].executionDate}</Dt></ReqdExctnDt>
      <Dbtr><Nm>{d.debtor.name}</Nm></Dbtr>
      <DbtrAcct><Id><IBAN>{d.debtor.iban}</IBAN></Id></DbtrAcct>
      <DbtrAgt><FinInstnId><Othr><Id>NOTPROVIDED</Id></Othr></FinInstnId></DbtrAgt>
      <CdtTrfTxInf>
        <PmtId><EndToEndId>{d.batches[i].payments[i].invoice}</EndToEndId></PmtId>
        <Amt><InstdAmt Ccy="EUR">{d.batches[i].payments[i].amount}</InstdAmt></Amt>
        <Cdtr><Nm>{d.batches[i].payments[i].name}</Nm></Cdtr>
        <CdtrAcct><Id><IBAN>{d.batches[i].payments[i].iban}</IBAN></Id></CdtrAcct>
      </CdtTrfTxInf>
      <CdtTrfTxInf>
        <PmtId><EndToEndId>{d.batches[i].payments[i+1].invoice}</EndToEndId></PmtId>
      </CdtTrfTxInf>
    </PmtInf>
    <PmtInf>
      <PmtInfId>{d.batches[i+1].id}</PmtInfId>
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>
```

**Result** ([nested-report.xml](/file/xml/nested-report.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.09">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>ACME-SCT-20261110-01</MsgId>
      <CreDtTm>2026-11-10T09:30:00+01:00</CreDtTm>
      <NbOfTxs>3</NbOfTxs>
      <CtrlSum>5530.41</CtrlSum>
      <InitgPty><Nm>Acme Corporation</Nm></InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>BATCH-20261112</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <NbOfTxs>2</NbOfTxs>
      <CtrlSum>2110.24</CtrlSum>
      <PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf>
      <ReqdExctnDt><Dt>2026-11-12</Dt></ReqdExctnDt>
      <Dbtr><Nm>Acme Corporation</Nm></Dbtr>
      <DbtrAcct><Id><IBAN>FR7630006000011234567890189</IBAN></Id></DbtrAcct>
      <DbtrAgt><FinInstnId><Othr><Id>NOTPROVIDED</Id></Othr></FinInstnId></DbtrAgt>
      <CdtTrfTxInf>
        <PmtId><EndToEndId>INV-88412</EndToEndId></PmtId>
        <Amt><InstdAmt Ccy="EUR">1249.99</InstdAmt></Amt>
        <Cdtr><Nm>Globex GmbH</Nm></Cdtr>
        <CdtrAcct><Id><IBAN>DE89370400440532013000</IBAN></Id></CdtrAcct>
      </CdtTrfTxInf>
      <CdtTrfTxInf>
        <PmtId><EndToEndId>INV-88419</EndToEndId></PmtId>
        <Amt><InstdAmt Ccy="EUR">860.25</InstdAmt></Amt>
        <Cdtr><Nm>Initech B.V.</Nm></Cdtr>
        <CdtrAcct><Id><IBAN>NL91ABNA0417164300</IBAN></Id></CdtrAcct>
      </CdtTrfTxInf>
      
    </PmtInf>
    <PmtInf>
      <PmtInfId>BATCH-20261115</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>3420.17</CtrlSum>
      <PmtTpInf><SvcLvl><Cd>SEPA</Cd></SvcLvl></PmtTpInf>
      <ReqdExctnDt><Dt>2026-11-15</Dt></ReqdExctnDt>
      <Dbtr><Nm>Acme Corporation</Nm></Dbtr>
      <DbtrAcct><Id><IBAN>FR7630006000011234567890189</IBAN></Id></DbtrAcct>
      <DbtrAgt><FinInstnId><Othr><Id>NOTPROVIDED</Id></Othr></FinInstnId></DbtrAgt>
      <CdtTrfTxInf>
        <PmtId><EndToEndId>INV-88433</EndToEndId></PmtId>
        <Amt><InstdAmt Ccy="EUR">3420.17</InstdAmt></Amt>
        <Cdtr><Nm>Umbrella Logistica S.L.</Nm></Cdtr>
        <CdtrAcct><Id><IBAN>ES9121000418450200051332</IBAN></Id></CdtrAcct>
      </CdtTrfTxInf>
      
    </PmtInf>
    
  </CstmrCdtTrfInitn>
</Document>
```

Learn more about [aggregators](/documentation/design/computation/aggregation.md).

## Numbers and dates

XML schemas expect machine formats, not the formats of a language. Use these formatters:

| Value | Tag | Result |
| --- | --- | --- |
| Date (`xs:date`) | `{d.date:formatD('YYYY-MM-DD')}` | 2026-11-12 |
| Date and time (`xs:dateTime`) | `{d.createdAt:formatD('YYYY-MM-DDTHH:mm:ssZ')}` | 2026-11-10T09:30:00+01:00 |
| Factur-X date (format 102) | `{d.issueDate:formatD('YYYYMMDD')}` | 20261110 |
| Decimal (`xs:decimal`) | `{d.total:round(2)}` | 3152.64 |

-   Dates with a time are converted to the `timezone` of the report, `Europe/Paris` by default. Dates without a time are not converted.
-   `:round(2)` writes a dot whatever the `lang` of the report, without trailing zeros: 49.9. When the receiver expects exactly two decimals, add `{o.lang=en-us}` to the template (it sets the language of the whole report) and write `{d.price:formatN(2):replace(',', '')}`: 49.90.
-   `:formatN` and `:formatC` alone add thousands separators and follow the language, like 1 234,50 in French.

See the [date](/documentation/design/formatters/date.md) and [number](/documentation/design/formatters/number.md) formatters, and [in-template options](/documentation/design/overview/in-template-options.md).

## Conditions

Schemas often reject empty elements. Remove an optional element when its value is missing, or print one value or another:

-   **Conditional blocks** remove the elements between `:showBegin` and `:showEnd` when the condition is false. In this Google Merchant Center feed, `{d.products[i].salePrice:ifNEM:showBegin}` keeps `g:sale_price` for the products on sale only, and each product gets either `g:gtin` or `g:identifier_exists`.
-   **Inline conditions** print one value or another: `{d.products[i].stock:ifGT(0):show('in_stock'):elseShow('out_of_stock')}`.

**Data** ([conditions-data.json](/file/xml/conditions-data.json)):

```json
{
  "store": {
    "name": "Acme Outdoor",
    "url": "https://shop.acme.example",
    "description": "Camping and hiking gear"
  },
  "products": [
    {
      "sku": "TNT-2P-GRN",
      "title": "Ridge 2-Person Tent & Footprint",
      "url": "https://shop.acme.example/p/ridge-tent?color=green&size=2p",
      "image": "https://shop.acme.example/img/ridge-tent-green.jpg",
      "stock": 34,
      "price": 249.99,
      "salePrice": 199.99,
      "brand": "Acme Outdoor",
      "gtin": "00012345678905"
    },
    {
      "sku": "LMP-HD-350",
      "title": "Trail Headlamp 350 lm",
      "url": "https://shop.acme.example/p/trail-headlamp",
      "image": "https://shop.acme.example/img/trail-headlamp.jpg",
      "stock": 0,
      "price": 39.95,
      "salePrice": null,
      "brand": "Acme Outdoor",
      "gtin": ""
    }
  ]
}
```

**Template** ([conditions-template.xml](/file/xml/conditions-template.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
  <channel>
    <title>{d.store.name}</title>
    <link>{d.store.url}</link>
    <description>{d.store.description}</description>
    <item>
      <g:id>{d.products[i].sku}</g:id>
      <title>{d.products[i].title}</title>
      <link>{d.products[i].url}</link>
      <g:image_link>{d.products[i].image}</g:image_link>
      <g:availability>{d.products[i].stock:ifGT(0):show('in_stock'):elseShow('out_of_stock')}</g:availability>
      <g:price>{d.products[i].price} USD</g:price>{d.products[i].salePrice:ifNEM:showBegin}
      <g:sale_price>{d.products[i].salePrice} USD</g:sale_price>{d.products[i].salePrice:showEnd}
      <g:brand>{d.products[i].brand}</g:brand>{d.products[i].gtin:ifNEM:showBegin}
      <g:gtin>{d.products[i].gtin}</g:gtin>{d.products[i].gtin:showEnd}{d.products[i].gtin:ifEM:showBegin}
      <g:identifier_exists>no</g:identifier_exists>{d.products[i].gtin:showEnd}
      <g:condition>new</g:condition>
    </item>
    <item>
      <g:id>{d.products[i+1].sku}</g:id>
    </item>
  </channel>
</rss>
```

**Result** ([conditions-report.xml](/file/xml/conditions-report.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
  <channel>
    <title>Acme Outdoor</title>
    <link>https://shop.acme.example</link>
    <description>Camping and hiking gear</description>
    <item>
      <g:id>TNT-2P-GRN</g:id>
      <title>Ridge 2-Person Tent &amp; Footprint</title>
      <link>https://shop.acme.example/p/ridge-tent?color=green&amp;size=2p</link>
      <g:image_link>https://shop.acme.example/img/ridge-tent-green.jpg</g:image_link>
      <g:availability>in_stock</g:availability>
      <g:price>249.99 USD</g:price>
      <g:sale_price>199.99 USD</g:sale_price>
      <g:brand>Acme Outdoor</g:brand>
      <g:gtin>00012345678905</g:gtin>
      <g:condition>new</g:condition>
    </item>
    <item>
      <g:id>LMP-HD-350</g:id>
      <title>Trail Headlamp 350 lm</title>
      <link>https://shop.acme.example/p/trail-headlamp</link>
      <g:image_link>https://shop.acme.example/img/trail-headlamp.jpg</g:image_link>
      <g:availability>out_of_stock</g:availability>
      <g:price>39.95 USD</g:price>
      <g:brand>Acme Outdoor</g:brand>
      <g:identifier_exists>no</g:identifier_exists>
      <g:condition>new</g:condition>
    </item>
    
  </channel>
</rss>
```

Write the begin tag at the end of the line above the block, and the end tag at the end of the last line of the block: the removed block leaves no empty line. `:hideBegin` and `:hideEnd` work the same way.

To remove an attribute, write the block inside the start tag: `<Contact{d.email:ifNEM:showBegin} email="{d.email}"{d.email:showEnd}>`. The template is no longer well-formed XML, but the report is. Learn more about [conditional blocks](/documentation/design/conditions/conditional-blocks.md) and [inline conditions](/documentation/design/conditions/inline-conditions.md).

## Totals

Math formatters and aggregators compute the amounts from the data. This Factur-X invoice uses the MINIMUM profile, which has no invoice lines: `{d.lines[].qty:mul(.price):aggSum}` computes the net total from the lines of the JSON data, and `:set` stores it in `c.net`. The tax and the totals below read `c.net`.

**Data** ([totals-data.json](/file/xml/totals-data.json)):

```json
{
  "number": "FA-2026-0417",
  "issueDate": "2026-11-10",
  "currency": "EUR",
  "vatRate": 20,
  "prepaid": 500,
  "seller": {
    "name": "Acme Corporation SAS",
    "siren": "999999998",
    "country": "FR",
    "vatId": "FR11999999998"
  },
  "buyer": {
    "name": "Globex SARL"
  },
  "lines": [
    { "name": "Cordless drill 18 V", "qty": 12, "price": 129.99 },
    { "name": "Battery pack 5 Ah", "qty": 24, "price": 64.49 },
    { "name": "Delivery", "qty": 1, "price": 45 }
  ]
}
```

**Template** ([totals-template.xml](/file/xml/totals-template.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
    xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
    xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
  <rsm:ExchangedDocumentContext>
    <ram:GuidelineSpecifiedDocumentContextParameter>
      <ram:ID>urn:factur-x.eu:1p0:minimum</ram:ID>
    </ram:GuidelineSpecifiedDocumentContextParameter>
  </rsm:ExchangedDocumentContext>
  <rsm:ExchangedDocument>
    <ram:ID>{d.number}</ram:ID>
    <ram:TypeCode>380</ram:TypeCode>
    <ram:IssueDateTime>
      <udt:DateTimeString format="102">{d.issueDate:formatD('YYYYMMDD')}</udt:DateTimeString>
    </ram:IssueDateTime>
  </rsm:ExchangedDocument>
  <rsm:SupplyChainTradeTransaction>
    <ram:ApplicableHeaderTradeAgreement>
      <ram:SellerTradeParty>
        <ram:Name>{d.seller.name}</ram:Name>
        <ram:SpecifiedLegalOrganization><ram:ID schemeID="0002">{d.seller.siren}</ram:ID></ram:SpecifiedLegalOrganization>
        <ram:PostalTradeAddress><ram:CountryID>{d.seller.country}</ram:CountryID></ram:PostalTradeAddress>
        <ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">{d.seller.vatId}</ram:ID></ram:SpecifiedTaxRegistration>
      </ram:SellerTradeParty>
      <ram:BuyerTradeParty>
        <ram:Name>{d.buyer.name}</ram:Name>
      </ram:BuyerTradeParty>
    </ram:ApplicableHeaderTradeAgreement>
    <ram:ApplicableHeaderTradeDelivery/>
    <ram:ApplicableHeaderTradeSettlement>{d.lines[].qty:mul(.price):aggSum:round(2):set(c.net)}
      <ram:InvoiceCurrencyCode>{d.currency}</ram:InvoiceCurrencyCode>{c.net:mul(d.vatRate):div(100):round(2):set(c.vat)}
      <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
        <ram:TaxBasisTotalAmount>{c.net}</ram:TaxBasisTotalAmount>
        <ram:TaxTotalAmount currencyID="{d.currency}">{c.vat}</ram:TaxTotalAmount>
        <ram:GrandTotalAmount>{c.net:add(c.vat):round(2)}</ram:GrandTotalAmount>
        <ram:DuePayableAmount>{c.net:add(c.vat):sub(d.prepaid):round(2)}</ram:DuePayableAmount>
      </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
    </ram:ApplicableHeaderTradeSettlement>
  </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>
```

**Result** ([totals-report.xml](/file/xml/totals-report.xml)):

```xml
<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
    xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
    xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
  <rsm:ExchangedDocumentContext>
    <ram:GuidelineSpecifiedDocumentContextParameter>
      <ram:ID>urn:factur-x.eu:1p0:minimum</ram:ID>
    </ram:GuidelineSpecifiedDocumentContextParameter>
  </rsm:ExchangedDocumentContext>
  <rsm:ExchangedDocument>
    <ram:ID>FA-2026-0417</ram:ID>
    <ram:TypeCode>380</ram:TypeCode>
    <ram:IssueDateTime>
      <udt:DateTimeString format="102">20261110</udt:DateTimeString>
    </ram:IssueDateTime>
  </rsm:ExchangedDocument>
  <rsm:SupplyChainTradeTransaction>
    <ram:ApplicableHeaderTradeAgreement>
      <ram:SellerTradeParty>
        <ram:Name>Acme Corporation SAS</ram:Name>
        <ram:SpecifiedLegalOrganization><ram:ID schemeID="0002">999999998</ram:ID></ram:SpecifiedLegalOrganization>
        <ram:PostalTradeAddress><ram:CountryID>FR</ram:CountryID></ram:PostalTradeAddress>
        <ram:SpecifiedTaxRegistration><ram:ID schemeID="VA">FR11999999998</ram:ID></ram:SpecifiedTaxRegistration>
      </ram:SellerTradeParty>
      <ram:BuyerTradeParty>
        <ram:Name>Globex SARL</ram:Name>
      </ram:BuyerTradeParty>
    </ram:ApplicableHeaderTradeAgreement>
    <ram:ApplicableHeaderTradeDelivery/>
    <ram:ApplicableHeaderTradeSettlement>
      <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
      <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
        <ram:TaxBasisTotalAmount>3152.64</ram:TaxBasisTotalAmount>
        <ram:TaxTotalAmount currencyID="EUR">630.53</ram:TaxTotalAmount>
        <ram:GrandTotalAmount>3783.17</ram:GrandTotalAmount>
        <ram:DuePayableAmount>3283.17</ram:DuePayableAmount>
      </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
    </ram:ApplicableHeaderTradeSettlement>
  </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>
```

A `:set` tag prints nothing. Write it at the end of a line, above the tags that read its value. Learn more about [math formatters](/documentation/design/computation/simple-mathematics.md) and [`:set`](/documentation/design/computation/store-and-transform.md).

The BASIC, EN 16931 and EXTENDED profiles add the invoice lines: repeat `ram:IncludedSupplyChainTradeLineItem` with a loop. To embed the XML in the PDF invoice, use [`:attachFile`](/documentation/design/advanced-features/file-operations.md#attachfile-name-type), as in the [Factur-X invoice example](/examples/factur-x/index.md).

## Best practices

-   **Attributes**: keep free text in elements, and codes or identifiers in attributes, like `currencyID="EUR"`. When an attribute holds free text, encode its double quotes: `{d.name:preserveCharRef:replace('"', '&#34;')}`. [Learn more](/documentation/design/formatters/text.md#preservecharref)
-   **Encoding**: save the template in UTF-8 and keep `encoding="UTF-8"` in the declaration. For a receiver that requires another encoding, send character references in the data, like `caf&#233;`, and add `:preserveCharRef` to the tag.
-   **Optional elements**: most schemas reject an empty date or amount. Remove these elements with a [conditional block](#conditions) when the value is missing.
-   **Validation**: before going live, check a few reports with the schema or the validator of the receiver.

## Automate an XML file

To generate an XML file from an XML template with the Carbone API:

1.  **Prepare two files**: an XML template with Carbone tags, like `{d.name}`, and the JSON data to populate it. You can use the files of the [Nested loops](#loops-nested-loops) example.
2.  **Generate the XML** in one of three ways:
    -   Use an official Carbone integration, like N8N, Make, Zapier, Airtable or Bubble.
    -   Use a Carbone SDK: Node.js, Go, Python, Java, JavaScript or PHP.
    -   Send a `POST /render/template` HTTP request to the [Carbone API](/documentation/developer/http-api/introduction.md), like this curl command:

```bash
curl --location --request POST 'https://api.carbone.io/render/template?download=true' \
  --header 'carbone-version: 5' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer API_TOKEN' \
  --data-raw "{
    \"data\": $(cat nested-data.json),
    \"template\": \"$(base64 -i nested-template.xml)\",
    \"timezone\": \"Europe/Paris\"
  }" \
  --output report.xml
```

> 💡 **Linux users**: replace `base64 -i nested-template.xml` with `base64 -w 0 nested-template.xml`

**Key parameters**

| Parameter | Description |
| --- | --- |
| `template` | Your XML template, encoded as a Base64 string. |
| `data` | JSON data used to populate the template. |
| `timezone` | Time zone of the dates and times printed by `:formatD`, like `"UTC"`. `"Europe/Paris"` by default. See [time zones](/documentation/developer/http-api/generate-reports.md#multi-timezone). |
| `lang` | Optional: language of the translations and of `:formatN` and `:formatC`. |
| `convertTo` | Omit it: an XML template generates an XML file. |
| `?download=true` | Query parameter to download the document as a stream. |
| `Authorization` | Header required for the Carbone Cloud API. [Get your API key here.](https://account.carbone.io/) |

For more details, refer to the [Carbone API Documentation](/documentation/developer/http-api/introduction.md).

## Related topics

- [XLSX templates](/documentation/design/template-formats/xlsx.md)
- [TXT templates](/documentation/design/template-formats/txt.md)
- [SVG templates](/documentation/design/template-formats/svg.md)
- [PPTX templates](/documentation/design/template-formats/pptx.md)
- [PDF templates](/documentation/design/template-formats/pdf.md)
- [Markdown templates](/documentation/design/template-formats/markdown.md)
