Modern ERP environments increasingly depend
on reliable, automated integration processes. After recent platform updates,
certain internal transformation capabilities within Dynamics 365 Finance &
Operations (D365FO) are restricted—especially those related to transforming
flat‑file formats (TXT/CSV) using XSLT inside the application.
This article presents a generic, scalable
approach using Azure Logic Apps to transform incoming transaction files (TXT →
XML) before they are imported into D365FO.
## 🌐 1. Overview
Many organizations receive credit card transaction files or similar flat‑file datasets from banking partners or external systems. After system updates, internal transformation using XSLT inside D365FO may no longer be supported, prompting the need for external transformation tools.
Use **Azure Logic Apps + Integration
Account** to handle external TXT‑to‑XML transformation, store processed XML
files in SharePoint (or Azure Storage), and finally import them into D365FO
using Data Management (DMF).
## 🔄 2. High-Level Architecture
```
[External System / Bank]
|
(TXT)
|
[SharePoint / Storage]
|
Trigger → Logic App
|
XSLT Mapping (Integration Account)
|
(XML Output)
|
[Processed Folder in SharePoint]
|
DMF Import to D365FO
## 🛠️ 3. End‑to‑End Process Flow
Logic App Implementation
3.1 Prerequisites / Access you need
- Azure subscription with permission to create resources
(Resource Group, Logic App, Integration Account, Storage Account).
- Resource Group where you will deploy resources.
- Storage Account with at least one container:
- incoming (where CSV is uploaded)
- output (where .xslt is saved)
- Integration Account (Enterprise
Integration) (required
for Flat File decoding and for Maps/XSLT). You must be owner or
contributor to create and link it.
- Permissions / credentials:
- Contributor / Logic App Operator on Logic
App resource.
- Storage Blob Data Contributor or access
keys (to let Logic App create/read blobs). You can use:
- Managed Identity for the Logic App +
RBAC on the Storage account (recommended), or
- Storage account connection using storage
account key / SAS.
The Logic App includes the following steps:
A. Create resources/ use existing
- Sign into Azure Portal.
- Create a Resource Group (if not
present).
- Create an Integration Account:
- Search "Integration Account" in
the portal -> Create.
- SKU: Standard (or depending on your
needs).
- Link it later to your Logic App (Standard
or Consumption) in the Logic App settings.
- Upload map (XSLT) to Integration
Account:
- In Integration Account -> Maps ->
Add -> Upload your .xslt file (choose type Map).
- Use XSLT generated form D365FO DMF
(Import project)àDownload.
B. Create the Logic App (Standard recommended)
- Create a Logic App (Standard):
- Resource type: Logic App (Standard)
- Plan: either create a new App Service
environment or use default single-tenant plan.
- On creation, in Workflow settings you can
link the Integration Account that you created.
- After creation, open the Logic App in
Designer.
C. Build the workflow (Designer) — exact actions &
settings
In the Logic App designer, create a Workflow
and add these actions
- When a file is created (properties only) —
Trigger on new file creation in SharePoint.
- Parameters -Site Address: https://yoursite.sharepoint.com/sites/d365/dev
- Folder- /AMEX Credit Card Transactions
- Code:
1. {
2. "type": "ApiConnection",
3. "inputs": {
4. "host": {
5. "connection": {
6. "referenceName": "sharepointonline-1"
7. }
8. },
9. "method": "get",
10. "path": "/datasets/@{encodeURIComponent(encodeURIComponent('https://yoursite.sharepoint.com/sites/d365/dev'))}/tables/@{encodeURIComponent(encodeURIComponent('cfcxxx696-e5a4-4c28-a2a7-60d7ff06fa1'))}/onnewfileitems",
11. "queries": {
12. "folderPath": "/AMEX
Credit Card Transactions"
13. }
14. },
15. "recurrence": {
16. "frequency": "Minute",
17. "interval": 2
18. },
19. "splitOn": "@triggerBody()?['value']"
20. }
- Initialize variable — To hold file content
temporarily.
- Name: Filecontent
- Type: string
- Code:
1. {
2. "type": "InitializeVariable",
3. "inputs": {
4. "variables": [
5. {
6. "name": "filecontent",
7. "type": "string"
8. }
9. ]
10. },
11. "runAfter": {}
12. }
- Get file content — Retrieve the uploaded
TXT file content.
- Site Address: https://yoursite.sharepoint.com/sites/d365/dev
- File identifier: Identifier
- Code:
1. {
2. "type": "ApiConnection",
3. "inputs": {
4. "host": {
5. "connection": {
6. "referenceName": "sharepointonline-1"
7. }
8. },
9. "method": "get",
10. "path": "/datasets/@{encodeURIComponent(encodeURIComponent('https://yoursite.sharepoint.com/sites/d365/dev'))}/files/@{encodeURIComponent(triggerBody()?['{Identifier}'])}/content",
11. "queries": {
12. "inferContentType": true
13. }
14. },
15. "runAfter": {
16. "Initialize_variable": [
17. "Succeeded"
18. ]
19. }
20. }
- Set variable — Assign file content to
variable.
- Name: filecontent
- Value: <Batch><![CDATA[
]]></Batch> - Code:
1. {
2. "type": "SetVariable",
3. "inputs": {
4. "name": "filecontent",
5. "value": "<Batch><![CDATA[@{body('Get_file_content')}\n]]></Batch>"
6. },
7. "runAfter": {
8. "Get_file_content": [
9. "Succeeded"
10. ]
11. }
12. }
- Transform XML (1) — Apply the first XSLT
transformation (TXT → XML).
- Content: filecontent
- Map Name: (select the Map(XSLT) which
uploaded in step 4 of A.
- Code:
1. {
2. "type": "Xslt",
3. "inputs": {
4. "content": "@variables('filecontent')",
5. "integrationAccount": {
6. "map": {
7. "name": "ECLAMEXTXT2AX"
8. }
9. }
10. },
11. "runAfter": {
12. "Set_variable": [
13. "Succeeded"
14. ]
15. }
16. }
- Transform XML (2) — Apply the second XSLT
transformation (XML → FinOps XML).
- Content: filecontent
- Map Name: (select the Map(XSLT) which
uploaded in step 4 of A.
- Code:
1. {
2. "type": "Xslt",
3. "inputs": {
4. "content": "@variables('filecontent')",
5. "integrationAccount": {
6. "map": {
7. "name": "ECLAMEXTXT2AX"
8. }
9. },
10. "transformOptions": "GenerateTextOutput"
11. },
12. "runAfter": {
13. "Transform_XML_1": [
14. "Succeeded"
15. ]
16. }
17. }
- Create file — Store the transformed XML in
the processed folder on SharePoint.
- Site Address: https://yoursite.sharepoint.com/sites/d365/dev
- Folder path: /Operations/AMEX Credit Card
Transactions/Processed
- File Name: name.xml
- File content : Transformed XML
- Code:
1. {
2. "type": "ApiConnection",
3. "inputs": {
4. "host": {
5. "connection": {
6. "referenceName": "sharepointonline-1"
7. }
8. },
9. "method": "post",
10. "body": "@body('Transform_XML')",
11. "path": "/datasets/@{encodeURIComponent(encodeURIComponent('https://yoursite.sharepoint.com/sites/d365/dev'))}/files",
12. "queries": {
13. "folderPath": "/Operations/AMEX
Credit Card Transactions/Processed",
14. "name": "@{triggerBody()?['{Name}']}.xml",
15. "queryParametersSingleEncoded": true
16. }
17. },
18. "runAfter": {
19. "Transform_XML": [
20. "Succeeded"
21. ]
22. },
23. "runtimeConfiguration": {
24. "contentTransfer": {
25. "transferMode": "Chunked"
26. }
27. }
28. }
No comments:
Post a Comment