# How to Access Office Document XML Directly Using OfficeCLI raw and raw-set with XPath

> Access Office document XML directly with OfficeCLI raw and raw-set commands. Use XPath to read and modify Word, PowerPoint, and Excel file parts. An escape hatch for complex needs.

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

---

**OfficeCLI exposes the underlying Open XML of Word, PowerPoint, and Excel files through two low-level verbs—`raw` to read parts and `raw-set` to modify them using XPath 1.0 expressions—effectively serving as an "escape hatch" when high-level typed verbs are insufficient.**

When you need to manipulate document elements that the standard OfficeCLI API does not expose—such as custom VML fallbacks, undocumented attributes, or complex nested structures—you can access Office document XML directly using OfficeCLI raw command with XPath. These commands bypass high-level schema validation and interact with the actual XML parts inside the Office Open XML ZIP package, giving you surgical precision over the document's internals.

## How the raw and raw-set Commands Work

The CLI parses these verbs in [`src/officecli/CommandBuilder.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/CommandBuilder.cs). When you invoke `raw`, the parser validates that a `part` argument is supplied and then dispatches to `handler.Raw(...)`【^1206-L1210】. For `raw-set`, the parser builds a parameter set including `part`, `xpath`, `action`, and optional `xml` payload, then forwards the request to `handler.RawSet(...)`【^1212-L1218】.

The actual implementation lives in format-specific handlers:
- **WordHandler.cs** handles `.docx` parts
- **PowerPointHandler.cs** handles `.pptx` parts  
- **ExcelHandler.cs** handles `.xlsx` parts

These handlers locate the requested part inside the ZIP package, load the XML, execute the supplied XPath expression, perform the requested mutation, and write the modified XML back into the package. Because these operations skip schema validation, they enable modifications that would otherwise be impossible through the typed verb layer.

## Identifying Internal Document Parts

Before querying XML, you must identify the correct internal part path. Office documents are ZIP archives containing XML files with well-known locations:

- **Word (.docx)**: `/document` (main body), `/styles`, [`/header1.xml`](https://github.com/iOfficeAI/OfficeCLI/blob/main//header1.xml), [`/footer1.xml`](https://github.com/iOfficeAI/OfficeCLI/blob/main//footer1.xml)
- **PowerPoint (.pptx)**: `/slide[1]`, `/slideMaster[1]`, `/presentation`
- **Excel (.xlsx)**: `/sheet[1]`, `/workbook`, `/styles`

The handlers automatically bind namespace prefixes for XPath queries: `w:` for Word, `p:` for PowerPoint, and `x:` for Excel.

## Reading Raw XML with the raw Command

The `raw` verb streams the entire XML content of a specified part as a single line, making it suitable for piping to parsers or grep.

### View the main document XML

```bash
officecli raw mydoc.docx /document | python -c "import sys,xml.etree.ElementTree as ET;root=ET.fromstring(sys.stdin.read());print(root.tag)"

```

This returns the root element tag (`w:document`) from the primary document part.

### Search for specific content

```bash
officecli raw mydoc.docx /document | grep -o '<w:p[^>]*>[^<]*Budget[^<]*</w:p>'

```

Because the output is collapsed to a single line, standard text processing tools can search for paragraph elements containing specific text without parsing the full XML tree.

## Modifying XML with XPath Using raw-set

The `raw-set` command accepts an XPath expression to target specific nodes and an `action` parameter defining the mutation type. Available actions include:

- **append**: Insert XML as the last child of the matched node
- **prepend**: Insert XML as the first child
- **insert-before**: Insert XML before the matched node
- **insert-after**: Insert XML after the matched node  
- **replace**: Swap the matched node with the supplied XML
- **remove**: Delete the matched node
- **setattr**: Add or update an attribute on the matched node

Actions requiring payload data expect an `--xml` argument containing the XML fragment or attribute assignment.

## Practical Examples by File Format

### Word: Add bookmark tags to a specific paragraph

```bash
officecli raw-set mydoc.docx /document \
  --xpath "//w:p[w:r/w:t='Introduction']" \
  --action append \
  --xml '<w:bookmarkStart w:id="99" w:name="intro"/><w:bookmarkEnd w:id="99"/>'

```

The XPath selects the paragraph containing the text "Introduction", and the `append` action inserts bookmark tags that no high-level verb exposes.

### Word: Replace text in a specific run

```bash
officecli raw-set mydoc.docx /document \
  --xpath "//w:r[w:t='Q1']" \
  --action replace \
  --xml '<w:r><w:t>Q2</w:t></w:r>'

```

This isolates the run element containing "Q1" and replaces the entire element with a new run containing "Q2".

### PowerPoint: Remove a shape by name

```bash
officecli raw-set deck.pptx /slide[3] \
  --xpath "//p:sp[p:nvSpPr/p:cNvPr[@name='Logo']]" \
  --action remove

```

Using the PowerPoint namespace prefix `p:`, this XPath finds a shape whose internal name is "Logo" on slide 3 and deletes it from the slide XML.

### Excel: Hide a worksheet by setting an attribute

```bash
officecli raw-set report.xlsx /sheet[2] \
  --xpath "//x:sheet[@name='Data']" \
  --action setattr \
  --xml 'state=hidden'

```

The `setattr` action adds the `state="hidden"` attribute to the sheet element, hiding the worksheet when opened in Excel.

## Summary

- **OfficeCLI** provides `raw` and `raw-set` as low-level "escape hatch" commands for direct Open XML manipulation
- **CommandBuilder.cs** dispatches these verbs to format-specific handlers (WordHandler.cs, PowerPointHandler.cs, ExcelHandler.cs)
- Use `raw` to stream XML content from internal parts like `/document`, `/slide[1]`, or `/sheet[1]`
- Use `raw-set` with XPath 1.0 and actions (`append`, `replace`, `remove`, etc.) to modify XML structure
- Namespace prefixes are automatically bound: `w:` for Word, `p:` for PowerPoint, `x:` for Excel
- These commands bypass schema validation, enabling access to undocumented or complex XML structures unavailable through typed verbs

## Frequently Asked Questions

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

The `raw` command is read-only and returns the XML content of a specified part, while `raw-set` performs write operations by executing XPath queries against that part and applying mutations such as appending, replacing, or removing nodes. According to the source in [`CommandBuilder.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/CommandBuilder.cs), `raw` calls `handler.Raw(...)` to retrieve data, whereas `raw-set` calls `handler.RawSet(...)` with additional parameters for the XPath and action type.

### Which namespace prefixes should I use in XPath expressions?

OfficeCLI handlers implicitly bind standard namespace prefixes so you do not need to declare them manually: use `w:` for WordprocessingML elements in `.docx` files, `p:` for PresentationML in `.pptx` files, and `x:` for SpreadsheetML in `.xlsx` files. These prefixes correspond to the default Open XML namespaces defined in the document parts.

### Can I use raw-set to modify any part of an Office document?

Yes, provided you know the internal part path and the XML structure, you can target any part within the ZIP package—including styles, headers, footers, slides, or workbook definitions—using the appropriate XPath expression and action. However, because `raw-set` bypasses high-level validation, you must ensure your modifications produce well-formed XML that conforms to the Office Open XML schema to avoid document corruption.

### Is there a risk of corrupting documents when using raw commands?

Since `raw` and `raw-set` bypass the schema validation and safety checks present in higher-level verbs, incorrect XPath expressions or malformed XML payloads can produce invalid documents that fail to open in Office applications. Always work on copies of documents when using these low-level commands, and validate your XPath expressions by inspecting the output of `raw` before attempting modifications with `raw-set`.