> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kasoftware.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 將 MySQL 輸出對映為 EDI 810 發票

> 從 MySQL 資料庫檢索資料，並在知行之橋中將其對映為 X12 810 EDI 發票文件。

export const companyName = "知行軟件";

export const siteNameShort = "知行之橋";

export const siteName = "知行之橋";

## 概觀

{siteName} 包含強大的工具，可以從後端資料庫中檢索目標資料，並將這些資料對映為出站 EDI 文件（如 X12、EDIFACT 等）。本指南逐步介紹建立 MySQL 資料庫到 EDI 工作流程的過程，重點是生成 X12 810 發票文件。範例發票遵循 Amazon 所需的語法。

本文中描述的方法和原理也適用於生成其他 EDI 文件，但從資料庫中提取的特定資料以及對映值之間的關係可能存在差異。

本指南從如何在 {siteNameShort} 中完成對映的概觀開始，然後逐步完成工作流程的每一步。請參閱 [範例資料](#範例資料) 檢視本文中使用的資料庫結構、輸出檔案以及生成的 810 文件。

## {siteName} 中的 EDI 對映

### 將 MySQL 資料提取為 XML

{siteNameShort} 使用 XML 作為通用格式，以完成資料轉換和操作。所有 EDI 對映工作流程都涉及將源資料（本例中為資料庫資料）和目標資料（本例中為 EDI 檔案）轉換為 XML。

所有從資料庫（或類資料庫應用程式）提取資料的 {siteNameShort} 端口都會自動將輸出資料格式化為 XML 檔案。因此，從資料庫中提取的資料可以立即進行對映或轉換。本指南使用 [MySQL 端口](../connectors/mysql/mysql) 與 MySQL 資料庫互動。

### 提取 810 發票相關的資料

通常會根據採購訂單 (PO) 向交易夥伴傳送發票。當製造公司收到請求一組製成品的採購訂單時，製造公司會以發票回應，以便收取所請求貨物的款項。

因此，用來生成發票的資料通常來自之前接收到的採購訂單。本文假設傳入的採購訂單資料會自動插入到資料庫中，所以採購訂單資料庫表儲存著與 810 發票相關的資料。為此工作流程配置 MySQL 端口時，MySQL 端口將指向儲存採購訂單資料的表。

採購訂單可以包含多個訂單行，並且典型的資料庫設定會將訂單行資料儲存在與 `PurchaseOrders` 表分開的 `LineItems` 表中。`LineItems` 表具有指向 `PurchaseOrders` 表的外部索引鍵，以便識別哪些訂單行與哪個採購訂單關聯，但必須從兩個表中提取資料才能檢索填充 810 發票所需的全部資訊。

[定義 SELECT 操作](#定義-select-操作) 包含同時從 `PurchaseOrders` 表和 `LineItems` 表（具有合適的外部索引鍵關係）提取資料所需的步驟。

### 將 EDI 文件表示為 XML

為了將從資料庫中提取的 XML 資料對映為 EDI 文件，EDI 文件也必須表示為 XML。{siteNameShort} 包括許多可以在 EDI 和 XML 格式（X12、EDIFACT 等）之間相互轉換的端口。本指南重點介紹對映 X12 文件，因此使用 [X12 端口](../connectors/x12) 生成目標 810 文件的 XML 表示。

在建立對映工作流程之前，準備一個範例輸出文件（例如範例 810）非常重要。該範例文件用於為對映步驟建立 XML 模型。您可以上傳自己的範例文件，也可以從內建範本清單中選擇。

### 轉換 XML 結構

一旦源格式和目標格式都表示為 XML，就可以使用強大的 [XML Map 端口](../connectors/xml-map/xml-map) 將一個 XML 結構轉換為另一個。

XML Map 端口需要範例 **源** 和 **目標** 範本檔案，分別代表起始和結束的 XML 結構。從資料庫中提取的 XML 輸出是來源檔案，而 X12 810 文件的 XML 表示（透過將範例 810 傳入 X12 端口生成）是目的檔案。

一旦指定源結構和目標結構，XML Map 端口的視覺化設計器將填充這兩個結構。源結構中的元素可以被拖拽到目標結構的元素上，以在兩者之間建立對映關係。此對映步驟需要理解 EDI 結構，這樣合適的元素才能包含在輸出檔案中。

XML Map 端口包括值格式化器、條件邏輯，甚至是自定義指令碼來在對映過程中操作和計算資料。有關這些功能的更多資訊，請參閱 [對映](../mapping/mapping)。

一旦對映關係建立，XML Map 端口可以自動將匹配源 XML 結構的檔案轉換為目標 XML 結構。在本例中，從資料庫中提取的資料會自動轉換為 X12 810 文件的 XML 模型。最後一步是採用 810 XML 檔案的 XML 模型並將其轉換為實際的 810 文件，透過 X12 端口可以輕鬆完成。

## 建立對映工作流程

本節包含在 {siteNameShort} 中建立工作流程的每一步，以檢索資料庫輸出並將其對映到 810 發票。

### 第 1 步：MySQL 端口

對映工作流程的第一步是配置 [MySQL 端口](../connectors/mysql/mysql)，以從 MySQL 資料庫中提取相關資料。

#### 建立連線

點選導覽列上的 **工作流程**，然後將一個 MySQL 端口例項新增到工作區畫布（參見 [設計工作流程](../flows/designing-a-flow) 瞭解說明）。對於生產環境的工作流程，MySQL 端口例項名稱應包含目標 MySQL 資料庫，以及關於正在從資料庫提取或推送的資料的上下文資訊（例如 MySQL\_Invoice\_tradingPartner）。在此工作流程中，為簡單起見，端口例項名稱為 **MySQL\_Output**。

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mysql_edi_1.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=f1d7a3dcca6f96b68d4a82eb6573a963" alt="MySQL connector on the workspace canvas" width="800" data-path="public/images/mysql_edi_1.png" />

從下拉式清單中選擇一個 **連線**，或單擊 **建立** 按鈕以建立新連線。下圖顯示了 **新增連線** 頁面。有關每個欄位的詳細資訊，請參閱 [建立連線](../connectors/mysql/mysql#establish-a-connection)。

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mysql_edi_connection_config.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=c4fd3c376a2f2c3362f34c3520e8f9e0" alt="MySQL Add Connection page" width="600" data-path="public/images/mysql_edi_connection_config.png" />

#### 定義 SELECT 操作

建立連線後，使用 [Select](../connectors/mysql/mysql-select) 操作從資料庫中提取相關資料。如 [提取 810 發票相關的資料](#提取-810-發票相關的資料) 中所述，資料是從父 `PurchaseOrders` 表和子 `LineItems` 表中提取的。

在 MySQL 端口 **系統設定** 頁面上，將 **操作** 設定為 `Select`。在 **Select 配置** 部分中，單擊 **新增** 以配置操作。這將顯示資料庫中的表清單。選擇父表（包含 PO 資料）。稍後將新增子表（包含行專案資料）。在此範例中，PO 表為 `test_purchase_orders`，選擇此表將填充配置部分的 **列** 區域。

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_db_output_mapping.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=e13e1379a74acf6eeb2a1a706efc6997" alt="MySQL Select configuration with test_purchase_orders table" width="800" data-path="public/images/mapmysql-810_db_output_mapping.png" />

使用編輯器選擇要檢索表中的哪些列；本指南在輸出 XML 中包含所有列。

表中的一列為 `Processed`，如果記錄尚未處理，則儲存值 `0`，如果已處理，則儲存值 `1`。當採購訂單被插入表中時，預期 `Processed` 列會設定為 `0`。Select 配置應僅在 `Processed` 列為 `0` 時提取記錄，並在成功提取記錄後將該列更新為 `1`。

要完成這一步，請應用過濾器，僅提取 `Processed` = `0` 的記錄。在編輯器的 **過濾器** 部分，增加一條新規則：

* 將左側下拉式清單設定為要檢查的列；本例中為 `Processed`
* 將中間下拉式清單設定為邏輯運算子；本例中為 `Equals`
* 將右側輸入設定為要與該列比較的值；本例中為 `0`

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_db_output_mapping_filtered.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=fa699b8a2ca1c2b29a319a862b11b7ef" alt="MySQL Select configuration with Processed filter" width="800" data-path="public/images/mapmysql-810_db_output_mapping_filtered.png" />

除了根據 `Processed` 列來過濾記錄，該列還需要被更新，這樣記錄不會被重複提取。編輯器中的 **高階** 部分允許指定當成功從資料庫中提取行時應更新的列。

在這種情況下，`Processed` 列應被更新為值 `1`。

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_db_output_mapping_filtered_updated.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=d822f8e6eecb61b1ef181120b81b576a" alt="MySQL Select configuration with update value for Processed column" width="700" data-path="public/images/mapmysql-810_db_output_mapping_filtered_updated.png" />

現在將從 `test_purchase_orders` 表中提取相應的記錄，您必須配置 **Select 配置** 部分，以提取與每個採購訂單相關的行專案。在此範例中，行專案資料儲存在 `test_po_line_items` 表中。

在 **Select 配置** 中，單擊 **新增** 以新增新的子表。選擇 `test_po_line_items` 表。編輯器會自動更新左側面板中的表樹結構。與第一個表一樣，您可以從 `test_po_line_items` 中選擇特定列進行輸出；本指南包含所有列。

當 MySQL 端口從 `test_purchase_orders` 表中提取一個採購訂單記錄時，它還會嘗試從 `test_po_line_items` 表中提取記錄。只有與當前採購訂單關聯的訂單行才應被提取，所以必須在子表上應用 `WHERE` 約束。

在本例中，`test_po_line_items` 表中的 `PONumber` 列對應 `test_purchase_orders` 表中的 `PONumber` 列。只有訂單行中的 `PONumber` 與採購訂單中的 `PONumber` 匹配時，記錄才應包含在採購訂單記錄的輸出中。

要完成該步驟，請在 `test_po_line_items` 配置的 **過濾器** 部分新增一條新規則：

* 將左側下拉式清單設定為子表中需要檢查的列；本例中為 `PONumber`
* 將中間下拉式清單設定為 `Equals`
* 將右側輸入設定為引用父表：單擊下拉箭頭並選擇 `REF`（出現 `$` 符號表示引用）
* 將最後一個輸入設定為父表中要比較的列；本例中同樣為 `PONumber`

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_db_output_mapping_full.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=cd8a0ecee4871569e81402fd48141fc3" alt="MySQL Select configuration with full parent-child relationship" width="800" data-path="public/images/mapmysql-810_db_output_mapping_full.png" />

配置現在已經完成，因此應在 MySQL 端口中儲存它。

配置儲存後，可以透過兩種方式從資料庫中提取資料。如果 MySQL 端口的 [自動化頁面](../connectors/database/database#automation-tab) 上啟用了 **接收自動化**，端口會根據接收間隔自動嘗試提取未處理的採購訂單（以及關聯的訂單行）。或者，您也可以導航到 **交易** 頁面並點選 **接收** 來手動提取記錄。在這兩種情況下，端口都會針對已配置的表執行 SELECT 查詢，並生成包含所選資料的輸出訊息。

#### SELECT 操作輸出為 XML

定義 Select 操作後，MySQL 端口將輸出表示為 XML。要檢視輸出的 XML 模型，請點選 **\</> 程式碼** 按鈕：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_output_mapping_code.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=c6ecc86f892c4e1343eb8183a42af953" alt="MySQL connector code view showing XML output structure" width="800" data-path="public/images/mapmysql-810_output_mapping_code.png" />

當 MySQL 端口從資料庫中提取資料時，它會使用檢索到的值填充具有此結構的 XML 文件。XML 檔案中的子結構可以重複。例如，如果為單個採購訂單提取多個訂單行，則 `test_po_line_items` 表對應的 XML 子部分會針對每個訂單行重複。

現在，該 XML 結構必須對映為表示 X12 810 發票的 XML 結構。然後，生成的對映 XML 可以直接轉換為 EDI 文件。

<Note>本指南中使用的對映位於 [資料庫 XML 結構](#資料庫-xml-結構)。</Note>

### 第 2 步：X12 端口

X12 端口在對映工作流程中充當兩個角色。

1. 它用於生成 810 發票的 XML 表示。這可以透過在 X12 端口的 **交易** 頁面上傳範例檔案，或使用隨 X12 端口提供的內建範本檔案來完成。在 X12 端口連線到 XML Map 端口後，上傳的範本檔案和內建範本檔案會顯示在 XML Map 端口的 **目標** 欄位中（以 `connector://` 為字首）。
2. 當 X12 端口將 XML Map 端口生成的 XML 轉換為 X12 文件時，它將執行工作流程中的最後一步。

將 X12 端口例項新增到畫布。X12 端口例項名稱通常應包括傳送 X12 文件的交易夥伴名稱。在此工作流程中，為簡單起見，例項名稱為 **XML\_To\_X12**。

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mysql_edi_2.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=23fcf486994aaa150fe82e63e721e6f7" alt="X12 connector added to the canvas" width="800" data-path="public/images/mysql_edi_2.png" />

#### 上傳測試檔案

如果已經有範例 810 發票檔案，**上傳測試檔案** 功能可簡化為目標 EDI 文件生成 XML 模型的過程。開啟 X12 端口 **交易** 頁面，然後單擊 **更多 > 上傳檔案**：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_upload_test_file.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=b85f2ed3de3b12f71b1924312b74ebe4" alt="Upload Files option on the X12 connector Transactions tab" width="800" data-path="public/images/mapmysql-810_upload_test_file.png" />

瀏覽並上傳範例 810 發票。X12 端口會在內部生成該文件的 XML 模型，XML Map 端口可以自動檢測到該模型。由於模型是內部儲存的，端口的外觀和配置不會發生變化。

如果沒有範例 810 檔案，則當您將 XML Map 端口連線到 X12 端口時，XML Map 端口 **系統設定** 頁面上的 **目的檔案** 欄位會填充可供選擇的內建範本檔案清單。有關更多資訊，請參閱 [選擇內建範本檔案](../connectors/xml-map/xml-map-template-files#choose-a-built-in-template-file)。

<Note>本指南中使用的範例 810 文件位於 [X12 810](#x12-810)。</Note>

#### 配置 X12 端口

除了建立一個範例 XML 模型，X12 端口還用於將 XML Map 端口對映的 XML 轉換為輸出 EDI 檔案。它還會根據端口中配置的設定向文件新增交換和功能群組資料。因此，必須根據將接收出站 X12 810 文件的交易夥伴的具體設定來配置 X12 端口。

在 X12 端口的 **系統設定** 頁面上，將 **轉換型別** 屬性設定為 `XML-to-X12`。在此模式下執行時，X12 端口的輸入應是結構化為 EDI 文件的 XML。使用前一步中 XML Map 端口的 **建立測試檔案** 選項，可確保輸入 XML 與此特定結構匹配。

預設情況下，勾選了 **動態處理夥伴**。這意味著端口會自動從 EDI 交易中識別並跟蹤交易夥伴關係。在這種情況下，不需要手動配置夥伴，因為端口會在許可限制內動態管理所有夥伴。本指南使用預設設定。請參閱 [X12 端口設定](../connectors/x12#connector-configuration) 瞭解取消勾選該項後需要執行的操作。

端口還會根據配置的設定填充交換和功能群組值。但是，交易夥伴可能需要進一步的交換 (ISA) 和功能群組 (GS) 值才能成功接收 810。請與交易夥伴明確溝通需要哪些標頭元素。有關更多資訊，請參閱 [X12 端口](../connectors/x12) 文件。

### 第 3 步：XML Map 端口

現在 MySQL 端口和 X12 端口已經分別生成了輸入和輸出資料的 XML 模型，使用 XML Map 端口將一個 XML 結構轉換為另一個。

將 XML Map 端口新增到工作流程，然後將 MySQL 端口連線到 XML Map 端口，將 XML Map 端口連線到 X12 端口。

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mysql_edi_3.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=cf0a785f6eeecb32eb281ec69b7da92c" alt="Full flow with MySQL, XML Map, and X12 connectors" width="800" data-path="public/images/mysql_edi_3.png" />

#### 配置 XML Map 端口

在 XML Map 端口的 **XML 對映** 頁面上，找到 **源** 和 **目標** 範本檔案欄位。端口會將 MySQL 端口 [Select 配置](#定義-select-操作) 中的 XML 模型檢測為可用的源範本檔案，並將 X12 端口測試檔案中的 XML 模型檢測為可用的目標範本檔案。如果任一選項不可用，請驗證測試檔案和配置是否已正確儲存，以及端口是否已在畫布上連線。

指定範本檔案後，XML Map 視覺化設計器會自動填充 MySQL Select 配置和範例 X12 810 檔案的 XML 結構。

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_designer.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=fa95b4146ae922d079bd9e6faa80ed58" alt="XML Map connector visual designer with MySQL and X12 structures" width="800" data-path="public/images/mapmysql-810_xml_map_designer.png" />

<Tip>如果目標結構中的 *Interchange* 和 *FunctionalGroup* 元素包含 *Meta* 元素，則可以安全地刪除它們。當將 XML 轉換為 EDI 時，X12 端口會將相關的中繼資料應用於 ISA 和 GS 段。</Tip>

#### 理解 XML 結構

要在 XML Map 端口中建立正確的對映關係，需要理解源結構和目標結構如何以 XML 表示。

結構中有兩種型別的 XML 元素（節點）。*父* 節點和 *葉* 節點定義了 XML 資料的層級結構，其中父節點對相關元素進行分組，葉節點代表要對映的實際資料值。使用父節點旁邊的展開和收起按鈕可以顯示或隱藏其葉節點。有關更多資訊，請參閱 [對映節點](../mapping/mapping-config#mapping-nodes)。

在 MySQL XML 中，每個父節點代表一張正在提取資料的表，每個葉節點代表該表中的一列。在 810 XML 中，每個 EDI *迴圈* 和 *段* 都是父節點，每個單獨的 EDI *元素* 都是葉節點。

## 建立對映

一旦 XML Map 端口配置了源結構和目標結構，就可以在設計器中拖拽節點來建立對映。

對映主要透過兩個步驟建立：

1. 在父節點之間建立 `Foreach` 迴圈關係
2. 在已建立的 `Foreach` 迴圈中對映葉節點之間的值

### 建立 Foreach 迴圈

`Foreach` 關係意味著每當源中出現一個元素時，就會在目標中建立一個新的 XML 結構。例如，如果源中的 *ElementA* 對映到目標中的 *ElementB*，輸入檔案中每次出現 *ElementA* 都會在輸出檔案中產生一個 *ElementB* 例項（以及所有 *ElementB* 的子元素）。

在這種情況下，從 PO 表 (`test_purchase_orders`) 中提取的每條記錄都會在生成的 EDI 中產生一個新的交易 (TX)，而從訂單項表 (`test_po_line_items`) 中提取的每條記錄都會產生一個新的 IT1Loop。將 *test\_purchase\_orders* 元素拖到 *TX-00401-810* 元素上，如下圖所示：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_foreach_1.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=82edcc7034f05aff3a2656bc2d9897c6" alt="將 test_purchase_orders 拖到 TX-00401-810 以建立 Foreach 迴圈" width="897" height="503" data-path="public/images/mapmysql-810_xml_map_foreach_1.png" />

現在將 *test\_po\_line\_items* 拖到 *IT1Loop1* 元素上，如下所示：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_foreach_2.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=8aa99010560ec9e2bb3bf58ece354fe5" alt="將 test_po_line_items 拖到 IT1Loop1" width="897" height="501" data-path="public/images/mapmysql-810_xml_map_foreach_2.png" />

<Note>用來建立目標結構的範例 X12 810 文件可能在對映設計器中顯示多個 *IT1Loop1* 元素。您可以刪除除一個之外的所有這些元素（右鍵單擊節點並選擇 **刪除節點**），因為 *Foreach* 關係會確保生成正確數量的 *IT1Loop1* 元素。</Note>

### 對映葉節點

建立 `Foreach` 關係後，可以對映迴圈中葉節點的值。對映葉節點決定了填充由 `Foreach` 迴圈建立的 XML 結構的值。

一些葉節點對映很簡單，另一些則需要使用 [節點值編輯器](../mapping/mapping-node-value-editor) 或 [程式碼指令碼編輯器](../mapping/mapping-config#code-script)。以下各節介紹 EDI 文件中常見的葉節點對映型別。有關更多資訊，請參閱 [對映](../mapping/mapping)。

#### 簡單葉節點對映

當來源檔案中的值應直接插入生成的輸出中時，只需將葉節點從源拖到目標中的葉節點上，即可對映這些值。此過程需要理解 EDI 目標格式，以及生成的 X12 文件中需要包含哪些值。

例如，X12 810 中的 *BIG04* 元素儲存了發票所對應的採購訂單編號。它對應資料庫輸出中的 *PONumber* 元素。將 *PONumber* 節點拖拽到 *BIG/BIG04* 節點上，以建立該關係。

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_one_leaf.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=4bdededee23bf6e26b4bb7f6d36bd1d4" alt="在 XML Map 端口中將 PONumber 對映到 BIG04" width="886" height="502" data-path="public/images/mapmysql-810_xml_map_one_leaf.png" />

對映目標節點右側的 xpath 表明對映值的來源（上圖中為 `PONumber`）。葉節點 xpath 與父節點中的 *Foreach* xpath（`/Items/test_purchase_orders`）相關。可以將所有父節點的 xpath 與葉節點中的 xpath 串聯起來，以在源 XML 中找到對映值的完整 xpath：`/Items/test_purchase_orders/PONumber`。

在本例中，其他直接的葉節點對映值包括以下內容：

* PODate > BIG/BIG03
* CurrencyCode > CUR/CUR02
* ItemID > IT1Loop1/IT1/IT107
* Quantity > IT1Loop1/IT1/IT102
* PricePerUnit > IT1Loop1/IT1/IT104
* PONumber（再次） > IT1Loop1/IT1/IT111

可以將這些源值逐個拖放到目標 EDI 文件中，無需修改或條件邏輯。

#### 上下文對映

一些葉節點對映取決於目標中的其他元素。例如，目標 XML 中的 *N1Loop1* 迴圈是表示 EDI 交易中的參與方或實體（例如開票方、收貨方、採購方等）的元素集合。*N1Loop1/N1/N101* 元素指示參與方的特定角色，而參與方的角色決定了應從源 XML 中對映哪些值。

在本指南中，源資料包括收貨方和收款方的詳細資訊。為了在 EDI 輸出中包含這些資料，需要兩個獨立的 *N1Loop1* 結構，一個將 *N1Loop1/N1/N101* 設定為 `ST`（ShipTo 的值），另一個設定為 `RI`（RemitTo 的值）。然後可以透過從源中拖放 *ShipToID* 和 *RemitToID*，對映每個相應迴圈的 *N1Loop1/N1/N102* 值：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_n1_leaf.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=c599ca8ccbd5d3f3939f9c056b92efcc" alt="將 ShipToID 和 RemitToID 對映到 N1Loop1 結構" width="898" height="502" data-path="public/images/mapmysql-810_xml_map_n1_leaf.png" />

將其他收貨方資料（*ShipToAddr*、*ShipToZip* 等）對映到 *N101* 設定為 `ST` 的 *N1Loop1* 結構中的 *N2*、*N3* 和 *N4* 元素。同樣，將其他收款方資料（*RemitToAddr*、*RemitToZip* 等）對映到 *N101* 設定為 `RI` 的 *N1Loop1* 結構中的適當元素。

<Note>一些 EDI 迴圈在 **目標** 對映中需要多個不同的節點（例如本節中的 *N1Loop1* 迴圈），而其他迴圈在目標對映中只需要一個節點（例如上一節中的 *IT1Loop1* 迴圈）。差異取決於 *Foreach* 關係是否會自動生成正確數量的輸出節點：由於 *N1Loop1* 節點沒有與其關聯的 *Foreach* 關係，因此目標對映需要顯式包含正確數量的 *N1Loop1* 節點。</Note>

#### 簡單計算

一些值不是直接從源 XML 中提取的，而是使用源中的一個或多個值計算得出。例如，每個 *IT1Loop1* 迴圈（即每個訂單行）都有一個 *TXI/TXI02* 元素，代表適用於該訂單行的稅額。源資料包含計算適用於購買的稅額所需的所有資訊：

* 單價
* 數量
* 稅率

然而，計算得到的稅額本身不存在於源中，因此必須在 XML Map 端口中計算。

[節點值編輯器](../mapping/mapping-node-value-editor) 中的 [格式化器](../scripting/value-formatters/formatters) 可用於在對映期間處理資料。在本例中，需要使用 [multiply](../scripting/value-formatters/number-formatters#multiply-value) 格式化器將源資料轉換為目標值。

從將 *PricePerUnit* 源節點對映到 *IT1Loop1/TXI/TXI02* 目標節點開始。這是生成合適數學運算式的良好起點，因為單價是運算式的輸入變數之一。然後，點選目標節點右側的平板和鉛筆 <img src="https://mintcdn.com/qiao/BoZrJ8_ctEN6h_9z/public/images/xmlmap_expressioneditor_icon.png?fit=max&auto=format&n=BoZrJ8_ctEN6h_9z&q=85&s=7ead9906fb7ee170d403e2536c8a545f" alt="tablet and pencil icon" noZoom style={{ display: "inline-block", verticalAlign: "middle", height: "0.9em", margin: 0 }} width="28" height="26" data-path="public/images/xmlmap_expressioneditor_icon.png" /> 圖示，開啟下圖所示的節點值編輯器：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_tax_expression_1.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=d15898f3775e4d007d2db57055566991" alt="Node Value Editor showing the initial tax expression" width="800" data-path="public/images/mapmysql-810_xml_map_tax_expression_1.png" />

將價格參數與數量相乘，得到該訂單行的總成本；使用豎線字元 (`|`) 將 *PricePerUnit* 值傳給 `multiply` 格式化器，然後將 `multiply` 格式化器的參數設定為 *Quantity* 源元素中的值：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_tax_expression_2.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=fd5bc74af91deaad48533ee4634d74ce" alt="Tax expression with multiply formatter for quantity" width="800" data-path="public/images/mapmysql-810_xml_map_tax_expression_2.png" />

<Note>*Quantity* 的 `xpath` 值必須用方括號括起來，才能解釋為動態值而不是字串文字。</Note>

此總成本值必須再乘以 *TaxPercent*，並乘以 .01 以從百分比轉換為貨幣值。完整運算式如下圖所示：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_tax_expression_3.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=e6725eebbcb25bf396b87f67bfd853b9" alt="Complete tax expression with TaxPercent and .01 multiplier" width="800" data-path="public/images/mapmysql-810_xml_map_tax_expression_3.png" />

儲存運算式後，對映會根據指定的動態輸入自動計算合適的值。

<Note>如前面的影像所示，使用節點值編輯器時，可以輕鬆搜尋格式化器和源文件中的資料。</Note>

#### 累加計算

輸出的 810 文件有一個 *TDS* 段，代表發票的總金額。彙總每個訂單行的成本需要一個可在每個訂單行迴圈中更新的持久變數。

需要指令碼將值儲存在變數中，並在之後的對映中檢索這些值。在 ArcScript 中，值儲存為 *屬性*，*專案* 是可以具有多個屬性的物件。專案屬性使用以下語法引用：`item_name.attribute_name`

`_map` 項是一個特殊項，會在整個文件對映過程中保留屬性值。換句話說，大多數屬性（變數）只會為單個節點對映保留，而 `_map` 項的屬性會在對映中的每個節點上保持不變。

為了彙總每個訂單行的成本，請在訂單行的 *Foreach* 迴圈中（即 *IT1Loop1* 迴圈）設定 `_map` 項的一個屬性。由於該指令碼沒有與 *IT1Loop1* 迴圈中的任何特定元素相關聯，因此應將專用的 [程式碼指令碼](../mapping/mapping-config#code-script) 元素新增到目標對映。該元素不會出現在生成的 EDI 文件中，但表示正在執行指令碼邏輯，以用於對映中的其他用途。

首先，右鍵單擊 *IT1Loop1* 元素並選擇 **新增節點 > 新增程式碼指令碼** 來新增一個新的程式碼指令碼元素（可以透過單擊並拖動來重新定位該元素）：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_tax_summation_1.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=15a96939770a9efa2f0616f668fdc5bb" alt="Adding a code script element to IT1Loop1" width="800" data-path="public/images/mapmysql-810_xml_map_tax_summation_1.png" />

此指令碼需要計算訂單行的完整成本，可透過以下公式得到：

`(PricePerUnit * Quantity) + (PricePerUnit * Quantity * TaxPercent * .01)`

編輯指令碼元素，用 ArcScript 表示以下公式。命名指令碼元素，然後點選 **新增指令碼**。

```xml theme={null}
<arc:set attr="lineItemCost" value="[xpath(PricePerUnit) | multiply([xpath(Quantity)])]" />
<arc:set attr="lineItemTax" value="[lineItemCost | multiply([xpath(TaxPercent)]) | multiply(.01) | round(2)]" />
<arc:set attr="_map.costSum" value="[_map.costSum | def(0) | add([lineItemCost]) | add([lineItemTax])]" />
```

在每個訂單行迴圈中執行完該指令碼之後，*\_map.costSum* 屬性會儲存所有訂單行的總成本（含稅）。要在 *TDS/TDS01* 元素中引用此值，請單擊 *TDS01* 元素右側的 `</>` 圖示並將 *result.text* 值設定為先前的屬性：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_tax_summation_after.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=3b9f010baebefd6d6b15230d104f4f26" alt="TDS01 element with _map.costSum reference" width="600" data-path="public/images/mapmysql-810_xml_map_tax_summation_after.png" />

#### 條件對映

一些節點需要條件邏輯來決定它們是否應出現在輸出中，以及其中應設定什麼值。例如，*ITD* 段包含有關發票條款的資料，而且只有在指定了條款時，才需要在輸出的 810 中包含該段。

可以使用目標對映中 *ITD* 元素旁邊的漏斗圖示來應用條件，決定該元素（以及它的子元素）是否出現在輸出文件中。單擊該圖示並在對映條件編輯器中新增一條規則；在本例中，採購訂單條款具有一個字首，用來表明是否必須在發票中指定條款：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_xml_map_condition.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=1b8aa3ac8ee9ef76593454bfea0c85ba" alt="Mapping condition editor for the ITD element" width="700" data-path="public/images/mapmysql-810_xml_map_condition.png" />

現在 *ITD* 元素只會在指定了特殊條款時出現，*ITD01* 元素需要儲存對應條款的合適程式碼。在本例中，以下值應用於關聯的條款：

* 02 - 加急付款
* 03 - 延遲付款
* 11 - 替代付款模式

輸入資料中 *Terms* 元素的值不能使用格式化器轉換為 *ITD01* 值，因此需要自定義指令碼來決定 *ITD01* 對映。編輯 *ITD01* 元素以開啟 **節點值編輯器**，然後使用 **指令碼模式** 切換項提供自定義指令碼。以下指令碼可完成上述模式：

```xml theme={null}
<arc:set attr="termsCode" value="" />
<arc:set attr="termsInput" value="[xpath(Terms)]" />

<arc:select value="[termsInput]">
 <arc:case value="Expedited Payment">
  <arc:set attr="termsCode" value="02" />
 </arc:case>
 <arc:case value="Delayed Payment">
  <arc:set attr="termsCode" value="03" />
 </arc:case>
 <arc:case value="Alternative Payment Profile">
  <arc:set attr="termsCode" value="11" />
 </arc:case>
</arc:select>

<arc:set attr='result.text'>[termsCode]</arc:set>
```

上述範例使用了 [arc:select](../scripting/keyword-reference/op-arc-select) 關鍵字，但也可以使用一系列 [arc:if](../scripting/keyword-reference/op-arc-if) 和 [arc:else](../scripting/keyword-reference/op-arc-else) 語句得到相同結果。

#### 索引對映

目標 XML 中的一些元素需要對 *Foreach* 關係中的迴圈次數進行計數。例如，*IT1Loop1/IT1/IT101* 元素儲存訂單行編號，因此需要為採購訂單中的每個訂單行遞增。同樣，*Meta/ST02* 元素需要為文件中的每個採購訂單遞增。

`_index` 屬性是一個特殊變數，儲存最區域性的 *Foreach* 迴圈關係的索引（對於巢狀的 *Foreach* 迴圈，`_index` 指最內層迴圈）。只要 *Foreach* 關係正確建立，就可以將 *Meta/ST02* 和 *IT1Loop1/IT1/IT101* 都設定為以下值，以正確統計採購訂單和訂單行：

`[_index]`

如果 *Foreach* 迴圈中的當前索引與更高階的對映邏輯相關，則此特殊屬性在任何自定義指令碼環境中也可用。

#### 在對映中生成日期

目標 XML 中的一些元素完全不引用源資料。*BIG/BIG01* 元素代表發票日期，該值直到當前對映步驟才可用。

可以使用特殊的 [now](../scripting/value-formatters/date-formatters#now-outputformat) 日期格式化器為當前日期時間生成新的日期值。像所有格式化器一樣，它可在任何節點對映的節點值編輯器中使用。

所有格式化器都需要一個輸入屬性來格式化。通常，在 XML 對映期間，輸入屬性是使用 `xpath` 格式化器檢索的值（也就是從源 XML 解析的值）。在本例中，傳給 `now` 格式化器的屬性並不重要，因為它始終傳回當前日期時間。因此，可以將預設 `_` 項作為佔位符傳遞：

<img src="https://mintcdn.com/qiao/3lMD3uYuGJqErRlJ/public/images/mapmysql-810_now_date.png?fit=max&auto=format&n=3lMD3uYuGJqErRlJ&q=85&s=bd3ee692f54065b4245dd820ba8e27d0" alt="Node Value Editor showing the now() date formatter" width="700" data-path="public/images/mapmysql-810_now_date.png" />

<Note>傳遞給 `now` 格式化器的參數定義了日期的輸出格式。</Note>

#### 計算訂單行和總成本

*CTT* 段包含用於計算訂單行總數的元素，以及表示專案總成本的雜湊值。計算這些值的方法與 [累加計算](#累加計算) 中描述的方法類似。

相關的值必須在可以使用訂單行資料的對映部分（即 *IT1Loop1* 部分）中進行計算，然後在之後的 *CTT* 對映中引用。這需要一個自定義指令碼，將值儲存在特殊的 `_map` 項中。

在 *IT1Loop1* 迴圈中（使用 *Foreach* 關係對映到 `test_po_line_items` 記錄），右鍵單擊並選擇 **新增節點 > 新增程式碼指令碼** 來新增新節點。指令碼會在每次對映迴圈時執行；換句話說，它會為每個訂單行執行一次。為了計算值，需要彙總行數和總成本，然後儲存在 `_map` 項的屬性中。

訂單行數量透過一個簡單的計數器計算，而成本可以使用 [累加計算](#累加計算) 中使用的相同公式計算。

```xml theme={null}
<arc:set attr="_map.lineItemCount" value="[_map.lineItemCount | def(0) | add(1)]">

<arc:set attr="currentCost" value="[xpath(PricePerUnit) | multiply([xpath(Quantity)])]" />
<arc:set attr="currentTax" value="[currentCost | multiply([xpath(TaxPercent)]) | multiply(.01) | round(2)]" />

<arc:set attr="_map.totalCost" value="[_map.totalCost | def(0) | add([lineItemCost]) | add([lineItemTax])]" />
```

*CTT01* 元素可以直接對映到 *\_map.lineItemCount*。開啟指令碼編輯器並引用先前的屬性：

```xml theme={null}
<arc:set attr="result.text">[_map.lineItemCount]</arc:set>
```

*CTT02* 元素可以對映到 *\_map.totalCost*。但是，*CTT* 雜湊要求忽略小數點，這裡等同於將成本乘以 100：

```xml theme={null}
<arc:set attr="result.text">[_map.lineItemCount | multiply(100)]</arc:set>
```

## 工作流程總結

MySQL 端口從後端系統中生成採購訂單資料的 XML，隨後 XML Map 端口將該 XML 對映為 EDI 格式。然後將 EDI XML 傳給 X12 端口，以新增交換頭並將 XML 轉換為 X12 格式。

此工作流程中最複雜的步驟是建立 XML 對映。對映需要在父節點之間建立 `Foreach` 關係，然後結合拖放操作、使用節點值編輯器、新增條件和編寫自定義指令碼來對映單個葉節點。

## 範例資料

### 資料庫 XML 結構

```xml theme={null}
<Items>
  <test_purchase_orders selectQuery="SELECT * FROM `test_purchase_orders` WHERE `Processed` = 0">
    <PONumber key="true" />
    <CurrencyCode />
    <CustomerID />
    <PODate type="datetime" />
    <Processed type="int" updateValue="1" />
    <RemitToAddr />
    <RemitToCountry />
    <RemitToID />
    <RemitToState />
    <RemitToZip />
    <ShipToAddr />
    <ShipToCountry />
    <ShipToID />
    <ShipToState />
    <ShipToZip />
    <Terms />
    <test_po_line_items selectQuery="SELECT * FROM `test_po_line_items` WHERE `PONumber` = ${PONumber}">
      <ItemID key="true" />
      <PONumber />
      <PricePerUnit type="double" />
      <Quantity type="int" />
      <TaxPercent type="double" />
    </test_po_line_items>
  </test_purchase_orders>
</Items>
```

### X12 810

```text theme={null}
ISA*00*          *00*          *ZZ*VENDOR         *ZZ*AMAZON         *090322*1001*U*00400*000001631*0*T*>~
GS*IN*VENDOR*AMAZON*20090322*1001*480*X*004010~
ST*810*0001~
BIG*20090320*5002841638*20090311*Q6515853~
CUR*BT*CAD~
N1*RI*VENDORNAME~
N3*PO BOX 1234~
N4*TORONTO*ON*M5W 5M5*CA~
N1*ST*AMAZON CANADA~
N3*500 MCCARTHY DR*FAIRVIEW BUSINESS PARK~
N4*MISSISSAUGA*ON*L5R 3W5*CA~
ITD*01*3*****60~
IT1*1*4*EA*12.6*NT*UP*786932788990*VN*1012380100000*PO*Q2515852~
TXI*GS*2.52*5~
IT1*2*30*EA*29.5*NT*UP*786936725951*VN*1000570100000*PO*Q2515852~
TXI*GS*44.25*5~
IT1*3*90*EA*22.5*NT*UP*782936735321*VN*0543900100000*PO*Q2515852~
TXI*GS*101.25*5~
IT1*4*5*EA*29.5*NT*UP*786936782268*VN*1000570200000*PO*Q2515852~
TXI*GS*7.38*5~
TDS*326330~
TXI*GS*155.4*5*****3108*954090650~
CTT*4*129~
SE*22*0001~
GE*1*480~
IEA*1*000001631~
```
