# When to Use Raw XML Access (L3) in OfficeCLI: A Complete Guide to Bypassing the DOM

> Unlock OfficeCLI's raw XML access (L3) when DOM limitations hinder your goals. Achieve perfect round-trip fidelity and boost performance for bulk updates. Explore this guide.

- Repository: [OfficeAI/OfficeCLI](https://github.com/iofficeai/OfficeCLI)
- Tags: how-to-guide
- Published: 2026-08-05

---

**Use OfficeCLI's raw XML access (L3) when the DOM layer cannot expose the element you need, when you require perfect round-trip fidelity, or when performing performance-critical bulk updates that would otherwise require full document parsing.**

The OfficeCLI project provides a layered architecture for manipulating Office documents programmatically. While the **Level 2 (L2) DOM API** handles most day-to-day editing through strongly-typed commands, the **Level 3 (L3) raw XML access** serves as an escape hatch for edge cases that the structured API cannot represent. Understanding when to use raw XML access in OfficeCLI helps you avoid workarounds and preserve document integrity.

## How OfficeCLI's Layered Architecture Works

OfficeCLI organizes its document manipulation capabilities into distinct levels. This design is evident in the command dispatcher at [`src/officecli/ResidentServer.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/ResidentServer.cs) ([line 1118](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/ResidentServer.cs#L1118)), where the verb determines which execution path to take.

| Level | Mechanism | Purpose |
|-------|-----------|---------|
| **L2** | Typed DOM API (`set`, `add`, `remove`, `move`) | Semantic, high-level operations with type safety |
| **L3** | Raw XML (`raw`, `raw-set`) | Direct XML fragment insertion and replacement |

The **DOM layer** parses Open XML into a strongly-typed object model. Commands like `set` manipulate properties by their semantic names, offering validation and auto-completion.

The **raw XML layer** bypasses this entirely. In [`src/officecli/CommandBuilder.Raw.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/CommandBuilder.Raw.cs), the `raw-set` verb accepts an explicit XPath and verbatim XML payload that gets inserted directly into the package.

## Four Scenarios Where Raw XML Access Becomes Necessary

### 1. Unexposed Elements and Obscure OOXML Attributes

The DOM implementation cannot cover every element in the sprawling OOXML specification. When you encounter **custom XML parts**, **obsolete schema elements**, or **newer schema extensions** that the typed API has not yet implemented, raw XML access is your only option.

In [`src/officecli/Handlers/Word/WordHandler.Set.Dispatch.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Handlers/Word/WordHandler.Set.Dispatch.cs) ([line 1052](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Handlers/Word/WordHandler.Set.Dispatch.cs#L1052)), the codebase explicitly falls back to `raw-set` when a typed setter encounters a property the SDK treats as unknown.

```bash

# L2 attempt fails: DOM does not recognize custom attribute

officecli set mydoc.docx /body/p[1] --prop myCustomAttr=42

# Error: property not found

# L3 solution: insert exact XML needed

officecli raw-set /body/p[1] --xpath "./w:p" \
    --xml '<w:p><w:r><w:t>Hello</w:t></w:r><w:myCustomAttr w:val="42"/></w:p>'

```

### 2. Perfect Round-Trip Fidelity Requirements

The DOM layer rewrites XML during serialization. For **embedded binary blobs**, **custom VML markup**, **legacy WordprocessingML elements**, or any content where precise byte-for-byte preservation matters, raw XML access prevents unwanted transformation.

As documented in [`src/officecli/Handlers/WordHandler.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Handlers/WordHandler.cs) ([line 518](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Handlers/WordHandler.cs#L518)), `raw-set` is specifically designed for "verbatim XML" scenarios where the structured API would otherwise alter or strip attributes.

### 3. Performance-Critical Bulk Operations

DOM operations incur overhead from parsing and re-serializing the entire document. For **batch updates across thousands of files** or **server-side automation pipelines**, raw XML access eliminates this bottleneck by operating on XML fragments directly.

```bash

# L3 for embedding binary data without DOM overhead

officecli raw-set /customXml --action embed-binary \
    --xml '<my:customXmlPart xmlns:my="http://example.com"><my:data/></my:customXmlPart>' \
    --binary-file ./payload.bin

```

The `embed-binary` action, implemented in the raw XML layer, handles binary data that the DOM cannot represent natively.

### 4. Binary Data and Custom Relationship Manipulation

When working with **embedded objects**, **ActiveX controls**, or **custom XML data parts**, the DOM's object model may lack the necessary abstractions. The raw XML layer's `embed-binary` action allows direct manipulation of relationships and binary streams.

## How the Codebase Decides Between L2 and L3

Understanding the internal dispatch logic helps predict when you'll need raw XML access. The [`ResidentServer.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ResidentServer.cs) file contains the central decision point:

```csharp
// Simplified representation of the dispatch logic at line 1118
switch (verb)
{
    case "raw":
    case "raw-set":
        // Bypass DOM entirely; hand off to raw XML handler
        ExecuteRawSet(command);
        break;
    default:
        // Route through typed DOM mutators
        ExecuteDomMutation(command);
        break;
}

```

Similarly, [`WordHandler.Set.Dispatch.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Set.Dispatch.cs) demonstrates **runtime fallback**: even when a property appears to be within the DOM's domain, the handler may redirect to `raw-set` if the typed implementation cannot express the required XML structure.

## Practical Decision Workflow

Follow this sequence when planning your OfficeCLI commands:

1. **Attempt L2 first**: Use `set`, `add`, `remove`, or `move` with semantic property names.

2. **Watch for failure modes**:
   - "Property not found" errors
   - Unexpected attribute stripping
   - Semantic names that don't map to your target XML

3. **Switch to L3 when**: The CLI cannot represent your target structure, or you need guaranteed preservation of markup.

4. **Construct precise `raw-set` commands**:
   - Specify an accurate `--xpath` for insertion point
   - Provide complete, valid XML in `--xml`
   - Use `--action embed-binary` for binary payloads

## Summary

- **Raw XML access (L3)** in OfficeCLI bypasses the DOM to insert verbatim XML fragments directly into the Open XML package.

- **Primary triggers for L3 usage**: missing DOM coverage for required elements, round-trip fidelity requirements, performance optimization, and binary data handling.

- **Key implementation files**: [`ResidentServer.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ResidentServer.cs) (dispatch logic), [`CommandBuilder.Raw.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/CommandBuilder.Raw.cs) (verb implementation), and [`WordHandler.Set.Dispatch.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Set.Dispatch.cs) (fallback behavior).

- **Always start with L2**, but recognize that `raw-set` is the intended and supported path for edge cases the typed API cannot express.

## Frequently Asked Questions

### How do I know if the DOM supports the property I need?

Attempt a `set` command with the semantic property name. If OfficeCLI returns a "property not found" error or if the resulting document lacks your expected changes, the DOM does not expose that element. Check the source at [`WordHandler.Set.Dispatch.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Set.Dispatch.cs) to see which properties have typed implementations.

### Can I mix L2 and L3 operations in the same document?

Yes. OfficeCLI processes commands sequentially, so you can perform DOM operations followed by raw XML modifications. The raw XML layer preserves existing DOM-managed content unless your XPath explicitly targets it for replacement.

### Does raw XML access bypass OfficeCLI's validation entirely?

Partially. While `raw-set` does not validate your XML against the DOM's type system, the underlying Open XML SDK still enforces package-level constraints. Malformed XML will fail at the package level, not the command level.

### Is there a performance penalty for using raw XML access when I don't need it?

Minimal for single operations, but cumulative in bulk scenarios. Raw XML avoids DOM parsing overhead, so it is actually faster for targeted changes. However, you lose the safety guarantees of the typed API—use it only when L2 is genuinely insufficient.