# `xml-disassembler`

[![NPM](https://img.shields.io/npm/v/xml-disassembler.svg?label=xml-disassembler)](https://www.npmjs.com/package/xml-disassembler)
[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/LICENSE.md)
[![Downloads/week](https://img.shields.io/npm/dw/xml-disassembler.svg)](https://npmjs.org/package/xml-disassembler)
[![Maintainability](https://qlty.sh/badges/e226ad95-4b8d-484a-9484-25862941262d/maintainability.svg)](https://qlty.sh/gh/mcarvin8/projects/xml-disassembler) [![Code Coverage](https://qlty.sh/badges/e226ad95-4b8d-484a-9484-25862941262d/test_coverage.svg)](https://qlty.sh/gh/mcarvin8/projects/xml-disassembler)
[![Known Vulnerabilities](https://snyk.io//test/github/mcarvin8/xml-disassembler/badge.svg?targetFile=package.json)](https://snyk.io//test/github/mcarvin8/xml-disassembler?targetFile=package.json)

Disassemble large XML files into smaller, modular files in formats like XML, INI, JSON, JSON5, TOML, or YAML—then reassemble them as needed.

Designed for improved version control, cleaner diffs, and easier team collaboration when dealing with complex XML structures.

---

## Features

- **Disassemble XML Files** – Break down XML into smaller components.
- **Reassemble XML** – Rebuild the original XML from disassembled parts.
- **Multiple Output Formats** – Choose XML, INI, JSON, JSON5, TOML, or YAML.
- **Two Disassembly Strategies** – Choose between `unique-id` (default) or `grouped-by-tag`.
- **Ignore Rules** – Exclude files from processing using an ignore file.
- **Logging** – Log errors and debug information using `log4js`.
- **Salesforce Integration** – Supports use cases like Salesforce metadata processing.

> **Note**: Reassembly guarantees element-level fidelity, but element order may vary—especially when using TOML.

<!-- TABLE OF CONTENTS -->
<details>
  <summary>Table of Contents</summary>

- [Background](#background)
- [Install](#install)
- [Disassembling Files](#disassembling-files)
- [Disassembly Strategies](#disassembly-strategies)
  - [unique-id (default)](#unique-id-default)
  - [grouped-by-tag](#grouped-by-tag)
- [Reassembling Files](#reassembling-files)
- [Use Case](#use-case)
- [Ignore File](#ignore-file)
- [XML Parser](#xml-parser)
- [Logging](#logging)
- [Contributing](#contributing)
- [Template & License](#template-&-license)
</details>

---

## Background

Managing large XML files—especially those generated by tools—can be painful. `xml-disassembler` solves this by splitting them into digestible pieces, optimized for Git diffs and team workflows.

No need for complex diffing tools—just structured directories with format-flexible files.

---

## Install

Install the package using NPM:

```
npm install xml-disassembler
```

---

## Disassembling Files

```typescript
import { DisassembleXMLFileHandler } from "xml-disassembler";

const handler = new DisassembleXMLFileHandler();
await handler.disassemble({
  filePath: "test/baselines/general",
  uniqueIdElements:
    "application,apexClass,name,externalDataSource,flow,object,apexPage,recordType,tab,field",
  prePurge: true,
  postPurge: true,
  ignorePath: ".xmldisassemblerignore",
  format: "json",
  strategy: "unique-id",
});
```

| Option             | Description                                                                            |
| ------------------ | -------------------------------------------------------------------------------------- |
| `filePath`         | Path to the XML file or directory                                                      |
| `uniqueIdElements` | Comma-separated list of UID elements for naming nested files                           |
| `prePurge`         | Delete previous disassembly output before running (`true` or `false`, default `false`) |
| `postPurge`        | Delete the original XML after disassembly (`true` or `false`, default `false`)         |
| `ignorePath`       | Path to the ignore file (default `.xmldisassemblerignore`)                             |
| `format`           | Output format: `xml`, `ini`, `json`, `json5`, `toml`, `yaml`                           |
| `strategy`         | Disassembly strategy: `unique-id` or `grouped-by-tag`                                  |

---

## Disassembly Strategies

### unique-id (default)

> This is the strategy all previous versions of the `xml-disassembler` follow.

Each nested element is written to a separate file based on its unique identifier—or a SHA-256 hash fallback. Leaf elements remain grouped in a file named after the original XML.

> Best for detailed diffs and granular version control.

**Example Outputs**

| Format    | UID Example                                                                                                              | Hash Example                                                                                                                     |
| --------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| **XML**   | ![XML UID](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled.png)<br>         | ![XML Hash](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-hashes.png)<br>         |
| **YAML**  | ![YAML UID](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-yaml.png)<br>   | ![YAML Hash](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-hashes-yaml.png)<br>   |
| **JSON**  | ![JSON UID](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-json.png)<br>   | ![JSON Hash](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-hashes-json.png)<br>   |
| **JSON5** | ![JSON5 UID](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-json5.png)<br> | ![JSON5 Hash](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-hashes-json5.png)<br> |
| **TOML**  | ![TOML UID](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-toml.png)<br>   | ![TOML Hash](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-hashes-toml.png)<br>   |
| **INI**   | ![INI UID](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-ini.png)<br>     | ![INI Hash](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-hashes-ini.png)<br>     |

### grouped-by-tag

Groups all nested elements by tag into a single file. Leaf elements still go into a base file named after the original XML.

> Best for fewer files and easier manual inspection.

**Example Outputs**

| Format    | Grouped by Tag Example                                                                                                        |
| --------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **XML**   | ![XML tag](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-tags.png)<br>         |
| **YAML**  | ![YAML tag](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-tags-yaml.png)<br>   |
| **JSON**  | ![JSON tag](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-tags-json.png)<br>   |
| **JSON5** | ![JSON5 tag](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-tags-json5.png)<br> |
| **TOML**  | ![TOML tag](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-tags-toml.png)<br>   |
| **INI**   | ![INI tag](https://raw.githubusercontent.com/mcarvin8/xml-disassembler/main/.github/images/disassembled-tags-ini.png)<br>     |

---

## Reassembling Files

```typescript
import { ReassembleXMLFileHandler } from "xml-disassembler";

const handler = new ReassembleXMLFileHandler();
await handler.reassemble({
  filePath: "test/baselines/general/HR_Admin",
  fileExtension: "permissionset-meta.xml",
  postPurge: true,
});
```

| Option          | Description                                                                                |
| --------------- | ------------------------------------------------------------------------------------------ |
| `filePath`      | Directory containing disassembled files to reassemble                                      |
| `fileExtension` | Extension for the output XML file (default: `.xml`)                                        |
| `postPurge`     | Delete disassembled files after successful reassembly (`true` or `false`, default `false`) |

---

## Use Case

See [`sf-decomposer`](https://github.com/mcarvin8/sf-decomposer) for a Salesforce CLI use case.

---

## Ignore File

Create an ignore file, similar to a `.gitignore`, to exclude XMLs from disassembly.

> uses [`node-ignore`](https://github.com/kaelzhang/node-ignore)

---

## XML Parser

Uses [`fast-xml-parser`](https://github.com/NaturalIntelligence/fast-xml-parser) with support for:

- Character Data (CDATA): `"![CDATA["`
- Comments: `"!---"`
- Attributes: `"@__**"`

---

## Logging

Logging uses [`log4js`](https://github.com/log4js-node/log4js-node). Logs are written to `disassemble.log`.

```typescript
import { setLogLevel } from "xml-disassembler";

setLogLevel("debug"); // Enables verbose logging
```

---

## Contributing

Contributions are welcome! See [Contributing](https://github.com/mcarvin8/xml-disassembler/blob/main/CONTRIBUTING.md).

---

## Template & License

This project is based on a template by [Allan Oricil](https://github.com/AllanOricil) and licensed under the ISC license. The original code remains under the [ISC license](https://github.com/mcarvin8/xml-disassembler/blob/main/LICENSE.isc).

All contributions specific to the `xml-disassembler` is licensed under the [MIT license](https://github.com/mcarvin8/xml-disassembler/blob/main/LICENSE.md).
