
Product
Socket Firewall Now Blocks Malicious VS Code and Open VSX Extensions
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.
@cerios/xml-poto
Advanced tools
TypeScript XML serialization library with decorator-based metadata. Supports namespaces, custom converters, validation, wrapped/unwrapped arrays, and bidirectional XML-object mapping.
A powerful TypeScript XML serialization library with decorator-based metadata. Provides type-safe, bidirectional XML-object mapping with support for namespaces, custom converters, validation, and flexible array handling.
npm install @cerios/xml-poto
npm install --save-dev @cerios/xml-poto
Note: This package uses standard TypeScript decorators and does not require
experimentalDecoratorsoremitDecoratorMetadatain yourtsconfig.json. It works with modern TypeScript configurations out of the box.
import { XmlRoot, XmlElement, XmlAttribute, XmlSerializer } from "@cerios/xml-poto";
// 1. Define your class with decorators
@XmlRoot({ elementName: "Person" })
class Person {
@XmlAttribute({ name: "id" })
id: string = "";
@XmlElement({ name: "Name" })
name: string = "";
@XmlElement({ name: "Email" })
email: string = "";
@XmlElement({ name: "Age" })
age?: number;
}
// 2. Create serializer
const serializer = new XmlSerializer();
// 3. Serialize to XML
const person = new Person();
person.id = "123";
person.name = "John Doe";
person.email = "john@example.com";
person.age = 30;
const xml = serializer.toXml(person);
console.log(xml);
// Output:
// <?xml version="1.0" encoding="UTF-8"?>
// <Person id="123">
// <Name>John Doe</Name>
// <Email>john@example.com</Email>
// <Age>30</Age>
// </Person>
// 4. Deserialize from XML
const xmlString = `
<Person id="456">
<Name>Jane Smith</Name>
<Email>jane@example.com</Email>
<Age>25</Age>
</Person>
`;
const deserializedPerson = serializer.fromXml(xmlString, Person);
console.log(deserializedPerson);
// Output: Person { id: '456', name: 'Jane Smith', email: 'jane@example.com', age: 25 }
Parse XML, modify it dynamically, and serialize back - perfect for XML transformation workflows:
import { XmlRoot, XmlDynamic, DynamicElement, XmlQuery, XmlSerializer } from "@cerios/xml-poto";
@XmlRoot({ elementName: "Catalog" })
class Catalog {
@XmlDynamic()
dynamic!: DynamicElement;
}
const xml = `
<Catalog>
<Product id="1"><Name>Laptop</Name><Price>999</Price></Product>
<Product id="2"><Name>Mouse</Name><Price>29</Price></Product>
</Catalog>
`;
const catalog = serializer.fromXml(xml, Catalog);
// Query and modify
const query = new XmlQuery([catalog.dynamic]);
query.find("Product").whereValueGreaterThan(100).setAttr("premium", "true");
// Add new elements
catalog.dynamic
.createChild({
name: "Product",
attributes: { id: "3" },
})
.createChild({ name: "Name", text: "Keyboard" });
// Serialize back to XML
const updatedXml = catalog.dynamic.toXml({ indent: " " });
See Bi-directional XML Guide for complete documentation.
Note: Use
DynamicElementand@XmlDynamicfor new code.DynamicElementand@XmlDynamicare deprecated but still supported.
xsi:nil, xsi:type, union types| Use Case | Feature | Documentation |
|---|---|---|
| REST API XML responses | Basic serialization | Getting Started |
| Configuration files | Nested objects, validation | Nested Objects |
| RSS/Atom feeds | Unwrapped arrays | Arrays |
| SOAP services | Namespaces | Namespaces |
| Blog content | Mixed content, CDATA | Mixed Content |
| Data extraction | Query API, XPath | Querying |
| Code documentation | CDATA, comments | CDATA |
| Decorator | Purpose | Example |
|---|---|---|
@XmlRoot | Define root element | @XmlRoot({ elementName: 'Person' }) |
@XmlElement | Map to element | @XmlElement({ name: 'Name' }) |
@XmlAttribute | Map to attribute | @XmlAttribute({ name: 'id' }) |
@XmlText | Map to text content | @XmlText() |
@XmlComment | Add XML comments | @XmlComment() |
@XmlArray | Configure arrays | @XmlArray({ itemName: 'Item' }) |
@XmlDynamic | Enable query API | @XmlDynamic() |
// Manual XML construction - error-prone
const xml = `<Person id="${id}"><Name>${name}</Name></Person>`;
// Manual parsing - tedious
const parser = new DOMParser();
const doc = parser.parseFromString(xml, "text/xml");
const name = doc.querySelector("Name")?.textContent;
// Type-safe, automatic, validated
const xml = serializer.toXml(person);
const person = serializer.fromXml(xml, Person);
Benefits:
@XmlRoot({ elementName: "Catalog" })
class Catalog {
@XmlDynamic() // Lazy-loaded and cached by default
query!: DynamicElement;
}
const catalog = serializer.fromXml(xmlString, Catalog);
// Use XPath-like queries (DynamicElement built on first access)
const titles = catalog.query.find("Product").find("Title").texts();
const expensiveItems = catalog.query.find("Product").whereValueGreaterThan(100);
// Navigate the tree
const parent = catalog.query.children[0].parent;
const siblings = catalog.query.children[0].siblings;
// Wrapped array
@XmlArray({ containerName: 'Books', itemName: 'Book', type: Book })
books: Book[] = [];
// <Books><Book>...</Book><Book>...</Book></Books>
// Unwrapped array
@XmlArray({ itemName: 'Item', type: Item })
items: Item[] = [];
// <Item>...</Item><Item>...</Item>
const ns = { uri: "http://example.com/schema", prefix: "ex" };
@XmlRoot({ elementName: "Document", namespace: ns })
class Document {
@XmlElement({ name: "Title", namespace: ns })
title: string = "";
}
// <ex:Document xmlns:ex="http://example.com/schema">
// <ex:Title>...</ex:Title>
// </ex:Document>
@XmlRoot({ elementName: "Article" })
class Article {
@XmlElement({ name: "Content", mixedContent: true })
content: any;
}
// Handles: <Content>Text <em>emphasis</em> more text</Content>
Learn more about Mixed Content →
@XmlAttribute({
name: 'email',
required: true,
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
})
email: string = '';
@XmlElement({
name: 'status',
enum: ['active', 'inactive', 'pending']
})
status: string = '';
const dateConverter = {
serialize: (date: Date) => date.toISOString(),
deserialize: (str: string) => new Date(str)
};
@XmlElement({ name: 'CreatedAt', converter: dateConverter })
createdAt: Date = new Date();
Initialize properties: Always provide default values
name: string = ""; // ✅ Good
name: string; // ❌ May cause issues
Specify types for arrays: Use the type parameter for complex objects
@XmlArray({ itemName: 'Item', type: Item })
items: Item[] = [];
Use validation for external data: Apply required, pattern, enum for untrusted XML
@XmlAttribute({ name: 'id', required: true, pattern: /^\d+$/ })
id: string = '';
Test round-trip serialization: Verify data integrity
const xml = serializer.toXml(original);
const restored = serializer.fromXml(xml, MyClass);
| Feature | xml-poto | Manual Parsing | Other Libraries |
|---|---|---|---|
| Type Safety | ✅ Full | ❌ None | ⚠️ Partial |
| Bidirectional | ✅ Yes | ❌ No | ✅ Yes |
| Decorators | ✅ Yes | ❌ No | ⚠️ Some |
| Query API | ✅ XPath-like | ❌ No | ❌ No |
| Namespaces | ✅ Full | ⚠️ Manual | ⚠️ Limited |
| Validation | ✅ Built-in | ❌ Manual | ⚠️ External |
| Mixed Content | ✅ Yes | ⚠️ Complex | ❌ No |
Contributions are welcome! Please see our Contributing Guide.
MIT © Ronald Veth - Cerios
Next Steps:
FAQs
TypeScript XML serialization library with decorator-based metadata. Supports namespaces, custom converters, validation, wrapped/unwrapped arrays, and bidirectional XML-object mapping.
We found that @cerios/xml-poto demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.

Research
More than 140 Mastra npm packages were compromised in a supply chain attack that used a typosquatted dependency to deliver a cross-platform infostealer during installation.

Research
/Security News
A new npm package tests AI malware scanners with prompt injection, safety-triggering comments, context flooding, and obfuscated JavaScript.