Skip to content

Serialize XDesign XML tree

Before report XML can be sent to xPression, it must be rendered from the .NET XDocument/XElement-derived tree (XDesignXDocument/XDesignXElement) into xPression's specific markup, with primary keys propagated down as foreign keys on descendant elements. This operation is the serialization step invoked internally by Render report (through ToXpression()) and is also available for callers building xPression payloads directly.

Field Value
Operation ID OP-PRT-09
Trigger Caller invokes XDesignXDocument.ToXpression() (delegates to the root element) or XDesignXElement.ToXpression() directly
Inputs An XDesignXDocument with an XDesignXElement root, or an XDesignXElement tree with AddKey-registered primary keys
Outputs Serialized xPression-compatible XML text
Primary components Reporting.XDesignXDocument.ToXpression, Reporting.XDesignXElement.ToXpression, Reporting.XDesignXElement.PropagateKeys
Entry point Services\SAIF.Services.Printing\Reporting\XDesignXDocument.vb, Services\SAIF.Services.Printing\Reporting\XDesignXElement.vb

Steps

  1. XDesignXDocument.ToXpression checks that the document's Root is not Nothing and is an XDesignXElement.
  2. If both conditions hold: it delegates to the root element's ToXpression().
  3. If not: it returns an empty string.
  4. XDesignXElement.ToXpression(tabIndex) is called with tabIndex = 0 for the root call.
  5. On the root call only (tabIndex = 0): the method first calls PropagateKeys(), which recursively walks every descendant XDesignXElement, clears its existing foreign-key list, adds each of the current element's Keys (primary keys registered via AddKey) as a foreign key on elements that have child elements, adds each inherited foreign key from the parent, and recurses into further descendants.
  6. If the current element has no child elements, ToXpression renders it as a single leaf element: its name and (HTML/XML-escaped) value via RenderElement.
  7. If the current element has child elements, ToXpression:
  8. Emits the opening tag via RenderStartElement.
  9. Emits each propagated foreign-key element (from step 2) via RenderElement, before any child content.
  10. Recurses into each child element, calling ToXpression(tabIndex + 1) on XDesignXElement children, or converting non-XDesignXElement children via the ToSAIFXElement extension method first.
  11. Emits the closing tag via RenderEndElement, followed by a line break when tabIndex > 0.
  12. Element values are escaped using System.Security.SecurityElement.Escape before being written, so XML-significant characters in report data do not break the generated markup.
  13. The fully serialized string is returned up the recursion to the original ToXpression caller.

Process flow

The following diagram visualizes the key-propagation and recursive rendering sequence.

flowchart TD
    Start([ToXpression called on document]) --> RootCheck{Root is<br>XDesignXElement?}
    RootCheck -->|No| Empty([Return empty string])
    RootCheck -->|Yes| Propagate[PropagateKeys: push primary keys<br>down as foreign keys on descendants]
    Propagate --> Leaf{Element has<br>child elements?}
    Leaf -->|No| RenderLeaf[Render as single<br>escaped leaf element]
    Leaf -->|Yes| OpenTag[Render opening tag]
    OpenTag --> FKeys[Render propagated<br>foreign-key elements]
    FKeys --> Recurse[Recurse into each<br>child element]
    Recurse --> CloseTag[Render closing tag]
    RenderLeaf --> End([Return serialized XML text])
    CloseTag --> End

Failure and edge-case behavior

  • Calling ToXpression() on a document whose root is not an XDesignXElement (for example, a plain XElement) returns an empty string rather than throwing or falling back to a generic serialization.
  • PropagateKeys only runs once, on the root call (tabIndex = 0); calling XDesignXElement.ToXpression directly on a non-root element with a non-zero tabIndex skips key propagation for that subtree.*
  • Foreign-key propagation only adds keys to descendant elements that already have their own child elements (x.HasElements); leaf descendants do not receive propagated foreign keys.

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts. Statements marked with ** could not be confirmed; treat as unknown until verified.

Sources

  • Services\SAIF.Services.Printing\Reporting\XDesignXDocument.vb
  • Services\SAIF.Services.Printing\Reporting\XDesignXElement.vb