Generate an XML Document
The warehouse partner that ships your sales orders pulls them from Business Central as XML, and their integration is strict: a document that does not parse is rejected, and a date or amount rendered with the server's regional settings ends up as garbage on their side. The previous attempt at this export glued the document together from strings — it worked until the first customer named O'Brien & Sons <Import/Export> came along.
Your job is an export codeunit that produces well-formed XML no matter what the data contains.
Requirements
Create a codeunit named "Sales Order Xml Export" with one public procedure:
procedure ExportOrder(OrderNo: Code[20]; ExportStream: OutStream)It writes an XML document describing the sales order with that No. to ExportStream. The document looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<SalesOrder no="101005" customerNo="10000" orderDate="2026-03-15">
<Customer>
<Name>O'Brien & Sons</Name>
</Customer>
<Lines>
<Line lineNo="10000" no="1896-S" description="ATHENS Desk" quantity="2.5" unitPrice="1234.56" />
<Line lineNo="20000" no="1900-S" description="PARIS Guest Chair" quantity="7" unitPrice="193.7" />
</Lines>
</SalesOrder>Rules:
- The root element is
SalesOrderwith three attributes:no= the order's"No.",customerNo= its"Sell-to Customer No.", andorderDate= its"Order Date"rendered asyyyy-mm-dd(for example2026-03-15) — regardless of the server's regional settings. - The root contains a
Customerelement with aNamechild element whose text content is the sell-to customer'sName, reproduced exactly — whatever apostrophes, ampersands or angle brackets it contains. - The root contains a
Lineselement with oneLineelement per sales line of the order, in ascending"Line No."order — whatever the line's type (items, G/L accounts, resources, ...). Lines whose"No."is empty are skipped entirely, and an empty"No."is the only thing that skips a line: a comment line is skipped because its"No."is empty, not because of its type. - Each
Lineelement carries five attributes:lineNo="Line No.",no="No.",description=Descriptionreproduced exactly,quantity=QuantityandunitPrice="Unit Price". Numbers use a dot as the decimal separator, no digit grouping (1234.5, never1,234.5or1.234,5) and the fewest digits needed — no trailing decimal zeros (193.7, never193.70) and no decimal point on whole numbers (7) — again regardless of regional settings. - The document starts with an XML declaration with version
1.0and encodingUTF-8(the casing of the encoding name is not graded). - The finished document is written to
ExportStreamand must re-parse as well-formed XML — special characters in names and descriptions have to survive a full write/read round trip.
What the tests check
The grading tests create sales orders with generated customers, items, quantities and prices, call ExportOrder into a temporary blob, re-parse the result with the platform's XML parser and assert nodes and attributes via XPath. Output that fails to parse fails every check, so escaping is non-negotiable: one test plants & ' < > in the customer name, another plants " & < > in a line description and expects both back character for character. Amounts above 1000 and a generated order date with single-digit day and month catch locale-dependent formatting and missing zero-padding; a line with quantity 7 at unit price 193.7 must render exactly those strings — no 7.00, no 193.70. The skip rule is graded from both sides: a description-only comment line and an item line with an empty "No." produce no Line element, while a G/L account line with a "No." produces one. Indentation, attribute order and the position of Customer relative to Lines inside the root are not graded — the parsed structure is.