XML

facet-xml maps Facet types to XML via explicit field annotations. This showcase highlights common serialization patterns and the new diagnostic you get when a field forgets to declare its XML role.

Serialization

Attributes, elements, and Vec fields

Attributes live on the root <ContactBook> tag while #[facet(xml::elements)] turns a Vec into repeated <contacts> children.

Target Type
#[derive(Facet)]
#[facet(xml::ns_all)]
struct ContactBook {
    #[facet(xml::attribute)]
    owner: String,
<span style="color:#e0af68;">#</span><span style="color:#a9b1d6;">[</span><span style="color:#e0af68;">facet</span><span style="color:#a9b1d6;">(</span><span style="color:#e0af68;">xml</span><span style="color:#a9b1d6;">::</span><span style="color:#e0af68;">elements</span><span style="color:#a9b1d6;">)]</span>
<span style="color:#7aa2f7;">contacts</span><span style="color:#a9b1d6;">:</span> <span style="color:#2ac3de;">Vec</span><span style="color:#a9b1d6;">&lt;</span><span style="color:#2ac3de;">Contact</span><span style="color:#a9b1d6;">&gt;,</span>

}

#[derive(Facet)] struct Contact { #[facet(xml::attribute)] id: u32,

<span style="color:#e0af68;">#</span><span style="color:#a9b1d6;">[</span><span style="color:#e0af68;">facet</span><span style="color:#a9b1d6;">(</span><span style="color:#e0af68;">xml</span><span style="color:#a9b1d6;">::</span><span style="color:#e0af68;">element</span><span style="color:#a9b1d6;">)]</span>
<span style="color:#7aa2f7;">name</span><span style="color:#a9b1d6;">:</span> <span style="color:#2ac3de;">String</span><span style="color:#a9b1d6;">,</span>

<span style="color:#e0af68;">#</span><span style="color:#a9b1d6;">[</span><span style="color:#e0af68;">facet</span><span style="color:#a9b1d6;">(</span><span style="color:#e0af68;">xml</span><span style="color:#a9b1d6;">::</span><span style="color:#e0af68;">element</span><span style="color:#a9b1d6;">)]</span>
<span style="color:#7aa2f7;">email</span><span style="color:#a9b1d6;">:</span> <span style="color:#2ac3de;">Option</span><span style="color:#a9b1d6;">&lt;</span><span style="color:#2ac3de;">String</span><span style="color:#a9b1d6;">&gt;,</span>

}

Value Input

ContactBook {
  owner"Operations",
  contactsVec<Contact> [
    Contact {
      id1,
      name"Alice",
      emailOption::Some("alice@example.com"),
    },
    Contact {
      id2,
      name"Bob",
      emailOption::None,
    },
  ],
}

XML Output

<ContactBook xmlns="https://example.com/contacts" owner="Operations">
  <Contact id="1">
    <name>Alice</name>
    <email>alice@example.com</email>
  </Contact>
  <Contact id="2">
    <name>Bob</name>

</Contact> </ContactBook>

xml::text for content

#[facet(xml::text)] captures character data inside an element, while attributes remain on the tag. This scenario deserializes the feed and pretty-prints the resulting Facet value.

XML Input

<AlertFeed severity="warning">
  <title>System Notices</title>
  <messages code="OPS-201">Deploying new release at 02:00 UTC</messages>
  <messages code="DB-503">Database failover test scheduled</messages>
</AlertFeed>
Target Type
#[derive(Facet)]
struct AlertFeed {
    #[facet(xml::attribute)]
    severity: String,
<span style="color:#e0af68;">#</span><span style="color:#a9b1d6;">[</span><span style="color:#e0af68;">facet</span><span style="color:#a9b1d6;">(</span><span style="color:#e0af68;">xml</span><span style="color:#a9b1d6;">::</span><span style="color:#e0af68;">element</span><span style="color:#a9b1d6;">)]</span>
<span style="color:#7aa2f7;">title</span><span style="color:#a9b1d6;">:</span> <span style="color:#2ac3de;">String</span><span style="color:#a9b1d6;">,</span>

<span style="color:#e0af68;">#</span><span style="color:#a9b1d6;">[</span><span style="color:#e0af68;">facet</span><span style="color:#a9b1d6;">(</span><span style="color:#e0af68;">xml</span><span style="color:#a9b1d6;">::</span><span style="color:#e0af68;">elements</span><span style="color:#a9b1d6;">)]</span>
<span style="color:#7aa2f7;">messages</span><span style="color:#a9b1d6;">:</span> <span style="color:#2ac3de;">Vec</span><span style="color:#a9b1d6;">&lt;</span><span style="color:#2ac3de;">AlertMessage</span><span style="color:#a9b1d6;">&gt;,</span>

}

#[derive(Facet)] struct AlertMessage { #[facet(xml::attribute)] code: String,

<span style="color:#e0af68;">#</span><span style="color:#a9b1d6;">[</span><span style="color:#e0af68;">facet</span><span style="color:#a9b1d6;">(</span><span style="color:#e0af68;">xml</span><span style="color:#a9b1d6;">::</span><span style="color:#e0af68;">text</span><span style="color:#a9b1d6;">)]</span>
<span style="color:#7aa2f7;">body</span><span style="color:#a9b1d6;">:</span> <span style="color:#2ac3de;">String</span><span style="color:#a9b1d6;">,</span>

}

Success

AlertFeed {
  severity"warning",
  title"System Notices",
  messagesVec<AlertMessage> [
    AlertMessage {
      code"OPS-201",
      body"Deploying new release at 02:00 UTC",
    },
    AlertMessage {
      code"DB-503",
      body"Database failover test scheduled",
    },
  ],
}

Diagnostics

Missing XML annotations

Every field must opt into XML via #[facet(xml::attribute/element/...)] (or #[facet(child)]). Leaving a field unannotated now produces a descriptive error before serialization begins.

Target Type
#[derive(Facet)]
struct MissingXmlAnnotations {
    title: String,
<span style="color:#7aa2f7;">details</span><span style="color:#a9b1d6;">:</span> <span style="color:#2ac3de;">String</span><span style="color:#a9b1d6;">,</span>

}

Value Input

MissingXmlAnnotations {
  title"Weekly Report",
  details"Compile-time errors per crate",
}

Error

xml::missing_xml_annotations

  × MissingXmlAnnotations cannot serialize because these fields lack XML annotations: title: String, details: String. Each field must opt into XML via one of:    • #[facet(xml::attribute)]  → <MissingXmlAnnotations field="…" /> (attributes)    • #[facet(xml::element)]    → <MissingXmlAnnotations><field>…</field></MissingXmlAnnotations> (single child)    • #[facet(xml::elements)]   → <MissingXmlAnnotations><field>…</field>…</MissingXmlAnnotations> (lists of children)    • #[facet(xml::text)]       → <MissingXmlAnnotations>…</MissingXmlAnnotations> (text content)    • #[facet(xml::element_name)] to capture the element/tag name itself.    `#[facet(child)]` is accepted as shorthand for xml::element. Use #[facet(flatten)] or #[facet(skip*)] if the field should be omitted.