# How to Use OfficeCLI Raw XML Commands for Direct XPath Manipulation

> Master OfficeCLI raw XML commands to directly manipulate OpenXML parts with XPath. Gain precise control over document structure by bypassing the object model.

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

---

**OfficeCLI exposes a low-level interface via `raw` and `raw-set` commands that let you read, edit, and validate OpenXML parts using standard XPath expressions, bypassing the high-level object model for precise control over document structure.**

OfficeCLI is an open-source command-line tool for automating Microsoft Office documents hosted at `iOfficeAI/OfficeCLI`. When you need to manipulate document elements that aren't exposed through standard high-level commands, the **OfficeCLI raw XML commands for direct XPath manipulation** provide direct access to the underlying OpenXML package parts, enabling surgical modifications to Word, Excel, and PowerPoint files.

## Core Architecture of Raw XML Processing

The raw XML functionality centers on three components implemented in the source tree:

- **`RawXmlHelper`** ([`src/officecli/Core/RawXmlHelper.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/RawXmlHelper.cs)): The central engine that loads XML parts, resolves namespaces, executes XPath queries against `XDocument` objects, and persists changes back to the package archive.

- **`CommandBuilder.Raw`** ([`src/officecli/CommandBuilder.Raw.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/CommandBuilder.Raw.cs)): Defines the CLI surface for the `raw` and `raw-set` sub-commands, parsing the required `--xpath` option and routing requests to the helper.

- **CLI Host** (`src/officecli/officecli.csproj`): Orchestrates the workflow by opening the target document, streaming the selected part to `RawXmlHelper`, and rendering results or error diagnostics via `OutputFormatter`.

When you invoke a raw command, the tool opens the Office document (`.docx`, `.xlsx`, `.pptx`), locates the requested part using the internal path model, constructs an `XmlNamespaceManager` from the part's declarations, and executes the XPath against the DOM. For write operations, the modified `XDocument` is serialized back into the ZIP archive while preserving relationships and document structure.

## Querying Document Structure with `raw`

The `raw` command performs read-only XPath evaluation against a specific document part. Use this to inspect elements, extract attribute values, or verify document structure before modification.

The XPath implementation uses **1-based indexing** that mirrors the Office CLI path model. For example, `/body/p[2]` selects the second paragraph, consistent with standard XML semantics.

```bash
officecli raw document.docx /document \
    --xpath "//w:tbl[w:tr][1]/w:tr[2]/w:tc[3]/w:p"

```

This query targets the first table in the document body, selects the second row and third cell, and returns the paragraph element(s) within that cell. The command outputs the raw XML of matched nodes, making it useful for discovering the exact structure before writing modifications.

To consume results programmatically, append the `--json` flag to receive a structured array of matches:

```bash
officecli raw presentation.pptx /slide[2] \
    --xpath "//a:blip/@r:embed" \
    --json

```

This returns JSON containing the relationship IDs of all images on slide 2, enabling downstream automation scripts to process embedded media.

## Modifying Content Using `raw-set`

The `raw-set` command follows the same resolution logic as `raw` but writes the transformed XML back to the document. This enables three primary operations: attribute modification, element insertion, and node deletion.

### Updating Attributes

Target an attribute node with `@` syntax and supply the replacement XML fragment via `--value`:

```bash
officecli raw-set document.docx /document \
    --xpath "//w:tbl[1]/w:tblPr/@w:tblW" \
    --value "<w:tblW w:w=\"5000\" w:type=\"dxa\"/>"

```

This locates the width attribute of the first table's properties and updates it to 5000 twips.

### Inserting Elements

When the XPath resolves to a container node, the supplied value is appended as a child:

```bash
officecli raw-set document.docx /document \
    --xpath "(//w:tbl)[1]/w:tr[last()]" \
    --value "<w:tr><w:tc><w:p><w:r><w:t>New row</w:t></w:r></w:p></w:tc></w:tr>"

```

This appends a new row to the end of the first table by targeting `w:tr[last()]` and injecting a complete table row fragment.

### Deleting Nodes

Pass an empty string to `--value` to remove all nodes matching the XPath:

```bash
officecli raw-set document.docx /document \
    --xpath "//w:p[not(w:r)]" \
    --value ""

```

This removes all empty paragraphs (those lacking text runs) from the document body.

## Namespace Handling and Error Diagnostics

OfficeCLI eliminates manual namespace management by automatically registering prefixes from the target part's declarations. You can use standard Office OpenXML prefixes—`w:` for WordprocessingML, `a:` for DrawingML, `r:` for relationships—without declaring them in your XPath expression.

The helper supports advanced XPath features including:

- **Wildcard selectors**: `*` matches any element
- **Attribute predicates**: `[@val='true']` filters by attribute value  
- **Position functions**: `[last()]` selects the final node in a set

Error handling is implemented in [`src/officecli/Core/OutputFormatter.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/OutputFormatter.cs), which surfaces actionable messages such as "XPath matched no elements" or "Expression must evaluate to a node-set" when queries fail validation. This prevents silent failures and helps debug malformed expressions.

Internal handlers like [`WordHandler.Navigation.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Navigation.cs) leverage these same raw commands for complex navigation scenarios, demonstrating that the XPath layer serves as the foundation for higher-level operations within the codebase.

## Summary

- **[`RawXmlHelper.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/RawXmlHelper.cs)** provides the core engine for loading, querying, and saving XML parts via XPath.
- The **`raw`** command enables read-only inspection of document structure using standard XPath 1.0 syntax.
- The **`raw-set`** command writes modifications back to the package, supporting attribute updates, element insertion, and node deletion.
- **Automatic namespace resolution** allows use of standard Office prefixes (`w:`, `a:`, `r:`) without manual declaration.
- **1-based indexing** in XPath predicates aligns with the Office CLI path model and standard XML conventions.

## Frequently Asked Questions

### What is the difference between `raw` and `raw-set` commands?

The `raw` command performs read-only queries against document parts and returns the matching XML nodes to stdout. The `raw-set` command performs the same query but expects a `--value` parameter; it replaces the matched nodes with the supplied XML fragment and writes the modified document back to the original file. According to the implementation in [`CommandBuilder.Raw.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/CommandBuilder.Raw.cs), both commands share the same XPath resolution logic but diverge at the persistence layer handled by `RawXmlHelper`.

### How does OfficeCLI handle XML namespaces in XPath queries?

OfficeCLI automatically constructs an `XmlNamespaceManager` from the namespace declarations present in the target OpenXML part. This allows you to use shorthand prefixes like `w:tbl` (Word), `a:blip` (DrawingML), or `r:embed` (Relationships) without manually mapping URIs. The resolution happens in [`RawXmlHelper.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/RawXmlHelper.cs) before the XPath is compiled, ensuring valid queries against namespaced elements.

### Can I use OfficeCLI raw commands to delete elements from a document?

Yes. To delete nodes, use the `raw-set` command with an empty string for the `--value` parameter. For example, `--xpath "//w:p[not(w:r)]" --value ""` removes all empty paragraphs. The helper treats an empty value as a deletion instruction and removes the matched nodes from the `XDocument` before saving.

### What happens if my XPath expression matches no elements?

If the XPath evaluates to an empty node-set, `RawXmlHelper` catches this condition and emits an error message through [`OutputFormatter.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/OutputFormatter.cs) stating "XPath matched no elements." The command exits with a non-zero status, preventing accidental no-op modifications. Similarly, if your expression returns a scalar value instead of a node-set when a node is expected, you'll receive "Expression must evaluate to a node-set."