Excelgoodies logo +40 31 2299227

LEARN THIS HANDS ON

Power Apps & Power Automate

. Live Online FILLING FAST
View all upcoming batches
Parsing e-Factura XML inside Power Automate: turning invoices into rows

Parsing e-Factura XML inside Power Automate: turning invoices into rows

Most Romanian finance teams now receive e-Factura invoices as XML, then manually copy values into Excel or an ERP just to archive and reconcile them. The files are structured but stuck in a document workflow. This walkthrough shows how to use Power Automate to parse e-Factura XML and turn every invoice into a clean row of data, ready for long‑term archiving or downstream processing.

Scenario: monthly e-Factura dump to a SharePoint archive

You have:

  • A dedicated mailbox that receives e-Factura XML attachments from suppliers or ANAF.
  • A SharePoint document library where finance drops all XMLs for the month.
  • A requirement from accounting: “we want a structured archive of invoices – one row per invoice, with totals and key IDs”.

No Power BI, no data warehouse. Just:

  • XML files stored in SharePoint.
  • A SharePoint list or Dataverse table to hold the parsed rows.
  • Power Automate as the glue.

We’ll build a flow that:

  1. Triggers when a new e-Factura XML file is added to SharePoint.
  2. Parses the XML into JSON using xml() in an expression.
  3. Extracts key invoice fields (invoice number, dates, supplier, customer, totals, currency).
  4. Writes one record per invoice into a SharePoint list.

The focus is on robust parsing and repeatable extraction, not on visualization.


Understanding the e-Factura XML structure (at a practical level)

Romania’s e-Factura is based on EN16931 / UBL 2.1. You’ll typically see an XML root like:

<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" 
         xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" 
         xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
  <cbc:ID>INV-2026-000123</cbc:ID>
  <cbc:IssueDate>2026-10-15</cbc:IssueDate>
  <cac:AccountingSupplierParty>
    <cac:Party>
      <cac:PartyLegalEntity>
        <cbc:RegistrationName>Supplier SRL</cbc:RegistrationName>
      </cac:PartyLegalEntity>
      <cac:PartyTaxScheme>
        <cbc:CompanyID>RO12345678</cbc:CompanyID>
      </cac:PartyTaxScheme>
    </cac:Party>
  </cac:AccountingSupplierParty>
  <cac:LegalMonetaryTotal>
    <cbc:PayableAmount currencyID="RON">1190.00</cbc:PayableAmount>
  </cac:LegalMonetaryTotal>
</Invoice>

Key points for Power Automate:

  • The XML uses namespaces (cbc:, cac: prefixes and a default xmlns on the root).
  • Power Automate’s xml() function converts this into a JSON object where:
    • Elements become properties.
    • Attributes become properties prefixed with @ (e.g. @currencyID).
  • The root element name (Invoice) becomes the top-level property in the JSON.

We’ll lean on this predictable structure to safely extract the fields we need.


Flow design: from SharePoint file to structured invoice row

We’ll implement the scenario with a single automated cloud flow.

1. Trigger on new e-Factura XML in SharePoint

Use the SharePoint connector:

  • Trigger: When a file is created (properties only)
  • Parameters:
    • Site Address: your finance site.
    • Library Name: the document library where XMLs are stored.

Optional but recommended:

  • Add a Condition early in the flow to check the file extension is .xml:
    • Expression: endsWith(triggerOutputs()?['body/{FilenameWithExtension}'], '.xml')

This avoids trying to parse PDFs or other attachments.

2. Get file content

Add action:

  • Get file content (SharePoint)
  • File Identifier: Identifier from the trigger.

This gives you a File content field which is the raw XML as text.

3. Convert XML to JSON with xml()

Power Automate has a built-in xml() expression that parses XML into a JSON object.

Add a Compose action:

  • Name: Parse XML to JSON
  • Inputs expression:
xml(body('Get_file_content')?['$content'])

Notes:

  • For the SharePoint Get file content action, the XML payload is in the $content property of the body; passing the entire body object to xml() will fail, so you must reference body('Get_file_content')?['$content'].
  • xml() returns a JSON object. Downstream actions can access it via outputs('Parse_XML_to_JSON').

If your flow uses a different connector (e.g. Outlook) you’d adapt the expression to the specific field that contains the XML string, but the pattern is the same.

4. Inspect the JSON shape with a test run

Before you start writing expressions, run the flow once with a sample e-Factura file, then:

  1. Open the Parse XML to JSON action.
  2. Use Peek code or open the output in the run history.

You should see a structure similar to:

{
  "Invoice": {
    "cbc:ID": "INV-2026-000123",
    "cbc:IssueDate": "2026-10-15",
    "cac:AccountingSupplierParty": {
      "cac:Party": {
        "cac:PartyLegalEntity": {
          "cbc:RegistrationName": "Supplier SRL"
        },
        "cac:PartyTaxScheme": {
          "cbc:CompanyID": "RO12345678"
        }
      }
    },
    "cac:LegalMonetaryTotal": {
      "cbc:PayableAmount": {
        "@currencyID": "RON",
        "#text": "1190.00"
      }
    }
  }
}

The exact namespaces may vary slightly, but you’ll see the same pattern:

  • Root object: Invoice.
  • Nested objects for cac: components.
  • Attributes as @... and element text as #text when the element has attributes.

We’ll use this JSON path in expressions to extract fields.


Extracting key invoice fields with expressions

For the archiving use case, most teams care about:

  • Invoice ID
  • Issue Date
  • Supplier name and VAT ID
  • Customer VAT ID (optional, depending on your process)
  • Total payable amount
  • Currency

We’ll create Compose actions for each field, then map them into a SharePoint list item.

1. Invoice ID

Add a Compose action:

  • Name: Invoice ID
  • Inputs expression:
outputs('Parse_XML_to_JSON')?['Invoice']?['cbc:ID']

This uses safe navigation (?) so a missing property returns null instead of failing the run.

2. Issue Date

Add Compose:

  • Name: Issue Date
  • Inputs:
outputs('Parse_XML_to_JSON')?['Invoice']?['cbc:IssueDate']

If you want to normalize to a specific format, you can wrap this in formatDateTime() later when writing to the list.

3. Supplier name

Add Compose:

  • Name: Supplier Name
  • Inputs:
outputs('Parse_XML_to_JSON')?['Invoice']?['cac:AccountingSupplierParty']?['cac:Party']?['cac:PartyLegalEntity']?['cbc:RegistrationName']

This path matches the typical UBL structure used by e-Factura.

4. Supplier VAT ID

Add Compose:

  • Name: Supplier VAT
  • Inputs:
outputs('Parse_XML_to_JSON')?['Invoice']?['cac:AccountingSupplierParty']?['cac:Party']?['cac:PartyTaxScheme']?['cbc:CompanyID']

If your sample XML uses a different element for the VAT ID, adjust the path based on your inspected JSON.

5. Payable amount and currency

In UBL, monetary elements with attributes are represented as objects with @ and #text keys.

Add Compose:

  • Name: Total Amount
  • Inputs:
outputs('Parse_XML_to_JSON')?['Invoice']?['cac:LegalMonetaryTotal']?['cbc:PayableAmount']?['#text']

Add Compose:

  • Name: Currency
  • Inputs:
outputs('Parse_XML_to_JSON')?['Invoice']?['cac:LegalMonetaryTotal']?['cbc:PayableAmount']?['@currencyID']

If your e-Factura files use a different element for totals (for example, if you need tax-exclusive amount instead), inspect the JSON and update the path accordingly.


Writing invoices into a SharePoint list

Create a SharePoint list for your archive, e.g. e-Factura Archive, with columns:

  • Title (default) – use for invoice ID or a composite key.
  • IssueDate (Date and Time).
  • SupplierName (Single line of text).
  • SupplierVAT (Single line of text).
  • TotalAmount (Number).
  • Currency (Single line of text).
  • Additional columns as needed.

In the flow, add action:

  • Create item (SharePoint)

Configure:

  • Site Address: same site.
  • List Name: e-Factura Archive.

Map fields:

  • Title:
outputs('Invoice_ID')
  • IssueDate (if SharePoint expects a date string):
formatDateTime(outputs('Issue_Date'), 'yyyy-MM-dd')
  • SupplierName:
outputs('Supplier_Name')
  • SupplierVAT:
outputs('Supplier_VAT')
  • TotalAmount:
outputs('Total_Amount')
  • Currency:
outputs('Currency')

Use the dynamic content picker or switch to expressions to reference the outputs of the Compose actions. The names in the expressions must match the action names in your flow.

At this point, every new e-Factura XML dropped into the SharePoint library produces one row in the archive list.


Handling common variations and failure modes

Real-world e-Factura files are not always identical. You’ll see:

  • Minor structural differences between providers.
  • Optional fields missing in some invoices.
  • Occasional malformed XML or non-e-Factura files in the same library.

Power Automate’s behaviour is deterministic here:

  • xml() fails if the input is not well‑formed XML.
  • Accessing a missing property without ? causes a runtime error.

1. Guarding against malformed XML

Add a Scope around the parsing and extraction actions, and configure run after on a fallback path.

Example pattern:

  1. Scope: Parse and extract invoice – contains Parse XML to JSON and all Compose actions.
  2. Scope: On parse failure – contains logging or notification actions.

Set On parse failure scope to run after Parse and extract invoice with the has failed condition.

Within On parse failure, you can:

  • Move the file to a separate library for manual review.
  • Send an email to a shared mailbox with the file name and error details.

2. Optional fields

Using ? in expressions already prevents hard failures for missing fields. For example, if cbc:CompanyID is missing, outputs('Supplier_VAT') will be null.

If you want a default value, wrap the expression in coalesce():

coalesce(
  outputs('Supplier_VAT'),
  'UNKNOWN'
)

Use this in the Create item action instead of the raw output.

3. Multiple invoices per file

If you ever receive a batch file with multiple Invoice elements under a root, xml() will return an array for that property. In that case, you’d:

  • Inspect the JSON and identify the array property (e.g. Invoices or multiple Invoice entries).
  • Add an Apply to each loop over that array.
  • Move the Compose and Create item actions inside the loop, adjusting paths to the current item.

The core pattern (JSON path extraction, safe navigation, writing rows) stays the same.


Performance and maintainability considerations

For typical monthly volumes of e-Factura XML in a mid‑size team, the described approach is well within Power Automate’s standard limits.

A few practical tips:

  • Keep JSON paths stable: When suppliers change their implementation, re‑inspect a sample file and update expressions. Document the current path patterns in the flow description.
  • Avoid unnecessary Parse JSON actions: The xml() output is already a JSON object; you can access it directly via expressions. Adding Parse JSON here adds maintenance overhead without functional benefit.
  • Use environment variables for site and list names if you plan to move the flow between environments (e.g. test → production).
  • Log the original file name in the archive list (add a column for it). This makes reconciliation and troubleshooting easier when something looks off.

In our scenario, this means the finance team can:

  • Drop XMLs into SharePoint as usual.
  • See a continuously growing list of structured invoice rows.
  • Filter, export, or link the list to other systems without touching the XML again.

One practical takeaway

When you need to archive e-Factura invoices as structured data, you don’t need a BI stack; a single Power Automate flow that uses xml() and careful JSON path expressions is enough to reliably turn every XML invoice into a row in SharePoint or Dataverse, ready for whatever your finance team wants to do next.

Editor's Note

This article reflects a growing pattern of finance and operations teams using Power Automate to turn Romania’s e-Factura XML streams into maintainable, row-based archives directly in SharePoint or Dataverse, without involving heavier BI tooling.

Professionals who want to apply these patterns to their own data can explore Excelgoodies' Power Automate Course programme - taught live by instructors, with certification awarded once a real project is running at work.

Insights compiled through ongoing industry research and discussions within the Excelgoodies Analytics Community.

Power Automate

New

Next Batches Now Live

Power BIPower BI
SQLSQL
Power AppsPower Apps
Power AutomatePower Automate
Microsoft FabricMicrosoft Fabrics
AzureAzure Data Engineering
Explore Dates & Reserve Your Spot → Reserve Your Spot →