# How to Use CSS-Style Selectors with OfficeCLI's `query` Command

> Master OfficeCLI query command CSS-style selectors for Word, Excel, and PowerPoint. Learn a consistent syntax for element selection, attribute filtering, and text matching across all document types. Boost your productivity now.

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

---

**OfficeCLI's `query` command implements a universal CSS-style selector engine that works across all supported document types (Word `.docx`, Excel `.xlsx`, PowerPoint `.pptx`) through a consistent syntax for element selection, attribute filtering, and text matching.**

The `query` sub-command is implemented in [`CommandBuilder.GetQuery.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/CommandBuilder.GetQuery.cs) and provides read-only access to document structures using familiar CSS-style selector patterns. This article explains the selector syntax, execution flow, and practical examples for each Office format.

## Selector Syntax Overview

OfficeCLI selectors support three core components that mirror CSS:

- **Element type** – `shape`, `paragraph`, `cell`, `image`, `picture`, `table`, etc.
- **Attribute filters** – `[fill=1E2761]`, `[width>=10cm]`, `[style=Heading1]`
- **Pseudo-selectors** – `:contains("text")`, `:empty`, `:no-alt`, `:has(formula)`, `:nth-child()`, `:first`, `:last`

Combine these for precise targeting: `table>row[height>2cm]:first` or `shape[fill=1E2761]:contains("Revenue")`.

## How the Query Engine Works

The execution flow involves four distinct layers, each implemented in specific source files.

### 1. Parsing the Selector String

The raw selector is parsed into a `SelectorPart` record defined in [`WordHandler.Selector.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Selector.cs). This parser is shared across document types and captures:

- Element name (`shape`, `paragraph`, `cell`)
- Attribute filter dictionary
- Optional `:contains()` text predicate
- Optional child/descendant selectors

### 2. Attribute Evaluation

`AttributeFilter.FilterSelector` in [`Core/AttributeFilter.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/Core/AttributeFilter.cs) implements the comparison engine. It supports:

| Operator | Meaning | Example |
|----------|---------|---------|
| `=` | exact match | `[fill=1E2761]` |
| `!=` | not equal | `[style!=Normal]` |
| `~=` | whitespace-separated list contains | `[class~=highlight]` |
| `>=`, `<=` | numeric comparison | `[width>=10cm]` |
| `[attr]` | existence check | `[alt]` |

This layer also handles pseudo-selectors like `:empty` and `:no-alt`.

### 3. Document-Specific Dispatch

[`ResidentServer.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ResidentServer.cs) routes filtered selectors to format-specific handlers:

- **Word** – [`WordHandler.Query.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Query.cs) matches `<w:p>`, `<w:r>`, `<w:tbl>` nodes
- **Excel** – [`ExcelHandler.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/ExcelHandler.cs) works on `<c>` cells and named ranges
- **PowerPoint** – [`PowerPointHandler.Query.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/PowerPointHandler.Query.cs) targets `<p:sp>`, `<p:pic>`, `<p:graphicFrame>` elements

### 4. JSON Result Shaping

Results are wrapped in a uniform envelope:

```json
{
  "data": {
    "results": [
      {
        "path": "/slide[3]/shape[2]",
        "format": { "id":"2","fill":"1E2761","textColor":"000000" },
        "name": "Revenue"
      }
    ]
  }
}

```

The complete schema is documented in each skill's [`SKILL.md`](https://github.com/iOfficeAI/OfficeCLI/blob/main/SKILL.md) file (e.g., [`skills/officecli-pptx/SKILL.md`](https://github.com/iOfficeAI/OfficeCLI/blob/main/skills/officecli-pptx/SKILL.md)).

## Practical Examples by Format

### Word Documents (.docx)

```bash

# Find all level-1 headings

officecli query "$FILE" 'paragraph[style=Heading1]' --json

# Locate images missing alt-text for accessibility audits

officecli query "$FILE" 'image:no-alt' --json

# Find tables with specific styling

officecli query "$FILE" 'table[style=TableGrid]>row:first' --json

```

### Excel Spreadsheets (.xlsx)

```bash

# List every formula cell

officecli query "$FILE" 'cell:has(formula)' --json

# Detect broken references

officecli query "$FILE" 'cell:contains("#REF!")' --json

# Filter by numeric value threshold

officecli query "$FILE" 'cell[value>=10000]' --json

```

### PowerPoint Presentations (.pptx)

```bash

# Search shapes containing "Revenue"

officecli query "$FILE" 'shape:contains("Revenue")' --json

# Find pictures without alt text

officecli query "$FILE" 'picture:no-alt' --json

# Filter shapes by exact fill color (hex)

officecli query "$FILE" 'shape[fill=1E2761]' --json

# Combine conditions: colored shapes with specific text

officecli query "$FILE" 'shape[fill=1E2761]:contains("Q3")' --json

```

## Post-Processing with jq

Pipe JSON output to `jq` for further analysis:

```bash

# Count matching results

officecli query "$FILE" 'shape:contains("Revenue")' --json |
  jq '.data.results | length'

# Extract first shape's ID for downstream automation

officecli query "$FILE" 'shape[fill=1E2761]' --json |
  jq -r '.data.results[0].format.id'

# Get all unique fill colors used

officecli query "$FILE" 'shape' --json |
  jq '[.data.results[].format.fill] | unique'

```

## Key Source Files

| File | Responsibility |
|------|--------------|
| [`src/officecli/CommandBuilder.GetQuery.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/CommandBuilder.GetQuery.cs) | CLI argument parsing, `query` command entry point |
| [`src/officecli/Core/AttributeFilter.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/AttributeFilter.cs) | Attribute comparison engine, pseudo-selector implementation |
| [`src/officecli/Handlers/Word/WordHandler.Selector.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Handlers/Word/WordHandler.Selector.cs) | Shared selector grammar parser |
| [`src/officecli/Handlers/Word/WordHandler.Query.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Handlers/Word/WordHandler.Query.cs) | Word-specific DOM traversal |
| [`src/officecli/Handlers/PowerPoint/PowerPointHandler.Query.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Handlers/PowerPoint/PowerPointHandler.Query.cs) | PPTX shape/picture/chart queries |
| [`src/officecli/Handlers/Excel/ExcelHandler.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Handlers/Excel/ExcelHandler.cs) | Cell and range selection logic |
| [`src/officecli/ResidentServer.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/ResidentServer.cs) | Handler dispatch and JSON result formatting |

## Extensibility Design

New document types integrate by implementing:

1. `ParseSelector()` – convert selector string to `SelectorPart` tree
2. `MatchesSelector()` – evaluate against native document model
3. Registration in `ResidentServer` handler dispatch table

This architecture keeps the CSS-style selector language **consistent across all Office formats** while allowing each handler to expose format-specific attributes.

## Summary

- OfficeCLI `query` provides **unified CSS-style selection** across Word, Excel, and PowerPoint
- Selectors combine **element types**, **attribute filters**, and **pseudo-selectors** in standard CSS syntax
- Core parsing lives in [`WordHandler.Selector.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/WordHandler.Selector.cs); evaluation runs through [`AttributeFilter.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/AttributeFilter.cs)
- Results return as **standardized JSON** suitable for piping to `jq` or other tools
- The handler-based architecture enables **consistent syntax** with **format-specific capabilities**

## Frequently Asked Questions

### What file formats support CSS-style selectors in OfficeCLI?

OfficeCLI's `query` command supports **Word `.docx`**, **Excel `.xlsx`**, and **PowerPoint `.pptx`** through dedicated handlers. Each format exposes its own element types (`paragraph` vs `cell` vs `shape`) but uses identical selector syntax. The handlers map generic selectors onto format-specific Open XML node types.

### How do I filter elements by text content?

Use the `:contains("text")` pseudo-selector. For example, `shape:contains("Revenue")` matches any shape containing that substring. For Excel formulas, use `:has(formula)` to detect formula cells. Text matching is case-sensitive and supports Unicode content.

### Can I combine multiple attribute conditions?

Yes. Chain filters without spaces: `shape[fill=1E2761][width>=10cm]:contains("Q3")`. The parser treats this as logical AND. For OR conditions, run separate queries and merge results with `jq`, as the selector engine does not implement CSS comma syntax.

### Where is the complete JSON output schema documented?

Each skill directory contains a [`SKILL.md`](https://github.com/iOfficeAI/OfficeCLI/blob/main/SKILL.md) file with the full schema. See [`skills/officecli-pptx/SKILL.md`](https://github.com/iOfficeAI/OfficeCLI/blob/main/skills/officecli-pptx/SKILL.md), [`skills/officecli-docx/SKILL.md`](https://github.com/iOfficeAI/OfficeCLI/blob/main/skills/officecli-docx/SKILL.md), and [`skills/officecli-xlsx/SKILL.md`](https://github.com/iOfficeAI/OfficeCLI/blob/main/skills/officecli-xlsx/SKILL.md) in the repository. All schemas share the top-level structure `{"data":{"results":[...]}}` with format-specific fields inside the `format` object.