🎯 Ejemplos recomendados
Balanced sample collections from various categories for you to explore
Ejemplos de Serialización de Datos Web TypeScript
Ejemplos de serialización de datos Web TypeScript incluyendo serialización/deserialización JSON y análisis XML
💻 Serialización JSON typescript
🟢 simple
⭐⭐⭐
Convertir objetos JavaScript a cadenas JSON con formato, reemplazos personalizados y manejo de referencias circulares
⏱️ 20 min
🏷️ typescript, web, serialization, json
Prerequisites:
Basic TypeScript, JSON API
// Web TypeScript JSON Serialization Examples
// Converting JavaScript objects to JSON strings with various options
// 1. Basic JSON Serialization
class JSONSerializer {
// Serialize to JSON string
stringify(obj: any, pretty: boolean = false): string {
if (pretty) {
return JSON.stringify(obj, null, 2);
}
return JSON.stringify(obj);
}
// Serialize with custom replacer
stringifyWithReplacer(obj: any, replacer: (key: string, value: any) => any): string {
return JSON.stringify(obj, replacer, 2);
}
// Serialize with date handling
stringifyWithDates(obj: any): string {
return JSON.stringify(obj, (key, value) => {
if (value instanceof Date) {
return { __type: 'Date', value: value.toISOString() };
}
return value;
}, 2);
}
// Serialize with undefined handling
stringifyWithUndefined(obj: any): string {
return JSON.stringify(obj, (key, value) => {
if (value === undefined) {
return null;
}
return value;
}, 2);
}
// Serialize with function handling
stringifyWithFunctions(obj: any): string {
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'function') {
return value.toString();
}
return value;
}, 2);
}
// Serialize with symbol handling
stringifyWithSymbols(obj: any): string {
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'symbol') {
return value.toString();
}
return value;
}, 2);
}
// Serialize with bigint handling
stringifyWithBigInt(obj: any): string {
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'bigint') {
return value.toString() + 'n';
}
return value;
}, 2);
}
}
// 2. Circular Reference Handler
class CircularReferenceHandler {
private seen = new WeakSet();
// Serialize with circular reference detection
stringify(obj: any): string {
this.seen = new WeakSet();
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (this.seen.has(value)) {
return '[Circular]';
}
this.seen.add(value);
}
return value;
}, 2);
}
// Serialize with circular reference path tracking
stringifyWithPath(obj: any): string {
const paths = new Map<any, string>();
let counter = 0;
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (paths.has(value)) {
return { $ref: paths.get(value) };
}
const path = `#${counter++}`;
paths.set(value, path);
return value;
}
return value;
}, 2);
}
// Serialize with circular reference replacement
stringifyWithReplacement(obj: any, replacement: any = null): string {
const seen = new WeakSet();
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return replacement;
}
seen.add(value);
}
return value;
}, 2);
}
}
// 3. Custom Type Serialization
class CustomTypeSerializer {
// Serialize with type metadata
serializeWithType(obj: any): string {
return JSON.stringify(obj, (key, value) => {
if (value instanceof Map) {
return { __type: 'Map', value: Array.from(value.entries()) };
}
if (value instanceof Set) {
return { __type: 'Set', value: Array.from(value) };
}
if (value instanceof Date) {
return { __type: 'Date', value: value.toISOString() };
}
if (value instanceof RegExp) {
return { __type: 'RegExp', value: { source: value.source, flags: value.flags } };
}
if (value instanceof Error) {
return { __type: 'Error', value: { name: value.name, message: value.message, stack: value.stack } };
}
if (typeof value === 'bigint') {
return { __type: 'BigInt', value: value.toString() };
}
return value;
}, 2);
}
// Serialize class instances
serializeClassInstance(obj: any): string {
return JSON.stringify(obj, (key, value) => {
if (value && typeof value === 'object' && value.constructor.name !== 'Object') {
return {
__class: value.constructor.name,
...value
};
}
return value;
}, 2);
}
// Serialize with custom type converters
serializeWithConverters(obj: any, converters: Map<string, (value: any) => any>): string {
return JSON.stringify(obj, (key, value) => {
for (const [type, converter] of converters) {
if (typeof value === type || value?.constructor?.name === type) {
return converter(value);
}
}
return value;
}, 2);
}
}
// 4. Compact JSON Serializer
class CompactSerializer {
// Minify JSON (remove whitespace)
minify(obj: any): string {
return JSON.stringify(obj);
}
// Compress property names
compressProperties(obj: any, mapping: Record<string, string>): string {
const compressed: any = Array.isArray(obj) ? [] : {};
for (const key in obj) {
const newKey = mapping[key] || key;
compressed[newKey] = obj[key];
}
return JSON.stringify(compressed);
}
// Remove null and undefined values
removeEmpty(obj: any): string {
const cleaned = this.removeEmptyValues(obj);
return JSON.stringify(cleaned);
}
private removeEmptyValues(obj: any): any {
if (obj === null || obj === undefined) {
return null;
}
if (Array.isArray(obj)) {
return obj.map(v => this.removeEmptyValues(v)).filter(v => v !== null);
}
if (typeof obj === 'object') {
const result: any = {};
for (const key in obj) {
const value = this.removeEmptyValues(obj[key]);
if (value !== null && value !== undefined) {
result[key] = value;
}
}
return result;
}
return obj;
}
// Sort keys for consistent output
sortKeys(obj: any): string {
const sorted = this.sortObjectKeys(obj);
return JSON.stringify(sorted, null, 2);
}
private sortObjectKeys(obj: any): any {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(v => this.sortObjectKeys(v));
}
const result: any = {};
const keys = Object.keys(obj).sort();
for (const key of keys) {
result[key] = this.sortObjectKeys(obj[key]);
}
return result;
}
}
// 5. Stream Serializer (for large objects)
class StreamSerializer {
// Chunk-based serialization
async serializeInChunks(obj: any, chunkSize: number = 1000): Promise<string> {
const json = JSON.stringify(obj);
const chunks: string[] = [];
for (let i = 0; i < json.length; i += chunkSize) {
chunks.push(json.slice(i, i + chunkSize));
}
return chunks.join('');
}
// Progressive serialization
async* serializeProgressively(obj: any): AsyncGenerator<string> {
const json = JSON.stringify(obj);
const chunkSize = 1000;
for (let i = 0; i < json.length; i += chunkSize) {
yield json.slice(i, Math.min(i + chunkSize, json.length));
}
}
}
// 6. Validation Serializer
class ValidationSerializer {
// Serialize with schema validation
serializeWithValidation(obj: any, schema: any): string {
this.validate(obj, schema);
return JSON.stringify(obj, null, 2);
}
private validate(obj: any, schema: any): void {
if (schema.type === 'object') {
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
throw new Error('Expected object');
}
if (schema.properties) {
for (const key in schema.properties) {
this.validate(obj[key], schema.properties[key]);
}
}
} else if (schema.type === 'array') {
if (!Array.isArray(obj)) {
throw new Error('Expected array');
}
if (schema.items) {
obj.forEach((item: any) => this.validate(item, schema.items));
}
} else if (schema.type === 'string') {
if (typeof obj !== 'string') {
throw new Error('Expected string');
}
} else if (schema.type === 'number') {
if (typeof obj !== 'number') {
throw new Error('Expected number');
}
} else if (schema.type === 'boolean') {
if (typeof obj !== 'boolean') {
throw new Error('Expected boolean');
}
}
}
// Serialize with size limit
serializeWithLimit(obj: any, maxSize: number): string {
const json = JSON.stringify(obj);
if (json.length > maxSize) {
throw new Error(`JSON size ${json.length} exceeds limit ${maxSize}`);
}
return json;
}
}
// 7. Filtered Serializer
class FilteredSerializer {
// Serialize with property filtering
serializeWithFilter(obj: any, include: string[]): string {
const filtered = this.filterProperties(obj, include);
return JSON.stringify(filtered, null, 2);
}
// Serialize with property exclusion
serializeWithExclusion(obj: any, exclude: string[]): string {
const filtered = this.excludeProperties(obj, exclude);
return JSON.stringify(filtered, null, 2);
}
// Serialize with depth limit
serializeWithDepth(obj: any, maxDepth: number, currentDepth: number = 0): string {
if (currentDepth >= maxDepth) {
return JSON.stringify(obj);
}
return JSON.stringify(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
if (Array.isArray(value)) {
return value.map(v => this.parseValue(v, maxDepth, currentDepth + 1));
}
const result: any = {};
for (const k in value) {
result[k] = this.parseValue(value[k], maxDepth, currentDepth + 1);
}
return result;
}
return value;
}, 2);
}
private filterProperties(obj: any, include: string[]): any {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(v => this.filterProperties(v, include));
}
const result: any = {};
for (const key of include) {
if (key in obj) {
result[key] = this.filterProperties(obj[key], include);
}
}
return result;
}
private excludeProperties(obj: any, exclude: string[]): any {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(v => this.excludeProperties(v, exclude));
}
const result: any = {};
for (const key in obj) {
if (!exclude.includes(key)) {
result[key] = this.excludeProperties(obj[key], exclude);
}
}
return result;
}
private parseValue(value: any, maxDepth: number, currentDepth: number): any {
if (currentDepth >= maxDepth) {
return typeof value === 'object' ? '[Max Depth Reached]' : value;
}
if (typeof value === 'object' && value !== null) {
if (Array.isArray(value)) {
return value.map(v => this.parseValue(v, maxDepth, currentDepth + 1));
}
const result: any = {};
for (const k in value) {
result[k] = this.parseValue(value[k], maxDepth, currentDepth + 1);
}
return result;
}
return value;
}
}
// Usage Examples
async function demonstrateJSONSerialization() {
console.log('=== Web TypeScript JSON Serialization Examples ===\n');
const serializer = new JSONSerializer();
const circularHandler = new CircularReferenceHandler();
const customSerializer = new CustomTypeSerializer();
const compactSerializer = new CompactSerializer();
const filteredSerializer = new FilteredSerializer();
// 1. Basic serialization
console.log('--- 1. Basic Serialization ---');
const obj1 = { name: 'Alice', age: 30, city: 'New York' };
console.log(serializer.stringify(obj1));
console.log(serializer.stringify(obj1, true));
// 2. Custom types
console.log('\n--- 2. Custom Type Serialization ---');
const obj2 = {
date: new Date(),
map: new Map([['key', 'value']]),
set: new Set([1, 2, 3]),
regex: /test/g
};
console.log(customSerializer.serializeWithType(obj2));
// 3. Circular references
console.log('\n--- 3. Circular Reference Handling ---');
const obj3: any = { name: 'Bob' };
obj3.self = obj3;
console.log(circularHandler.stringify(obj3));
// 4. Filtered serialization
console.log('\n--- 4. Filtered Serialization ---');
const obj4 = {
id: 1,
name: 'Charlie',
password: 'secret',
email: '[email protected]'
};
console.log(filteredSerializer.serializeWithExclusion(obj4, ['password']));
// 5. Compact serialization
console.log('\n--- 5. Compact Serialization ---');
const obj5 = { a: 1, b: null, c: undefined, d: 2 };
console.log(compactSerializer.removeEmpty(obj5));
console.log('\n=== All JSON Serialization Examples Completed ===');
}
// Export functions
export { JSONSerializer, CircularReferenceHandler, CustomTypeSerializer, CompactSerializer, StreamSerializer, ValidationSerializer, FilteredSerializer };
export { demonstrateJSONSerialization };
💻 Deserialización JSON typescript
🟡 intermediate
⭐⭐⭐
Analizar cadenas JSON a objetos JavaScript con revivers, conversión de tipos y manejo de errores
⏱️ 25 min
🏷️ typescript, web, serialization, json
Prerequisites:
Intermediate TypeScript, JSON API
// Web TypeScript JSON Deserialization Examples
// Parsing JSON strings to JavaScript objects with various options
// 1. Basic JSON Deserialization
class JSONDeserializer {
// Parse JSON string
parse<T = any>(json: string): T {
return JSON.parse(json);
}
// Parse with custom reviver
parseWithReviver<T = any>(json: string, reviver: (key: string, value: any) => any): T {
return JSON.parse(json, reviver);
}
// Parse with date handling
parseWithDates<T = any>(json: string): T {
return JSON.parse(json, (key, value) => {
if (typeof value === 'string') {
// Try to parse as date
const date = new Date(value);
if (!isNaN(date.getTime())) {
return date;
}
}
return value;
});
}
// Safe parse with error handling
safeParse<T = any>(json: string, defaultValue: T): T {
try {
return JSON.parse(json);
} catch (error) {
console.error('JSON parse error:', error);
return defaultValue;
}
}
// Parse with validation
parseWithValidation<T = any>(json: string, validator: (obj: any) => boolean): T | null {
try {
const obj = JSON.parse(json);
if (validator(obj)) {
return obj;
}
return null;
} catch (error) {
console.error('JSON parse error:', error);
return null;
}
}
}
// 2. Custom Type Deserialization
class CustomTypeDeserializer {
// Deserialize with type metadata
deserializeWithType<T = any>(json: string): T {
return JSON.parse(json, (key, value) => {
if (value && typeof value === 'object' && value.__type) {
switch (value.__type) {
case 'Date':
return new Date(value.value);
case 'Map':
return new Map(value.value);
case 'Set':
return new Set(value.value);
case 'RegExp':
return new RegExp(value.value.source, value.value.flags);
case 'Error':
const error = new Error(value.value.message);
error.name = value.value.name;
error.stack = value.value.stack;
return error;
case 'BigInt':
return BigInt(value.value);
default:
return value;
}
}
return value;
});
}
// Deserialize class instances
deserializeClassInstance<T = any>(json: string): T {
return JSON.parse(json, (key, value) => {
if (value && typeof value === 'object' && value.__class) {
// Would need class registry for actual instantiation
const { __class, ...data } = value;
return data;
}
return value;
});
}
// Deserialize with custom converters
deserializeWithConverters<T = any>(
json: string,
converters: Map<string, (value: any) => any>
): T {
return JSON.parse(json, (key, value) => {
if (value && typeof value === 'object' && value.__type) {
const converter = converters.get(value.__type);
if (converter) {
return converter(value.value);
}
}
return value;
});
}
}
// 3. Schema-Based Deserializer
class SchemaDeserializer {
// Deserialize with schema validation
deserializeWithSchema<T = any>(json: string, schema: any): T | null {
try {
const obj = JSON.parse(json);
if (this.validate(obj, schema)) {
return this.transform(obj, schema);
}
return null;
} catch (error) {
console.error('JSON parse error:', error);
return null;
}
}
// Deserialize with type coercion
deserializeWithCoercion<T = any>(json: string, types: Record<string, string>): T {
const obj = JSON.parse(json);
for (const key in types) {
if (key in obj) {
obj[key] = this.coerceType(obj[key], types[key]);
}
}
return obj;
}
private validate(obj: any, schema: any): boolean {
if (schema.type === 'object') {
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
return false;
}
if (schema.required) {
for (const field of schema.required) {
if (!(field in obj)) {
return false;
}
}
}
} else if (schema.type === 'array') {
if (!Array.isArray(obj)) {
return false;
}
}
return true;
}
private transform(obj: any, schema: any): any {
if (schema.type === 'object' && schema.properties) {
for (const key in schema.properties) {
if (key in obj) {
obj[key] = this.coerceType(obj[key], schema.properties[key].type);
}
}
}
return obj;
}
private coerceType(value: any, type: string): any {
switch (type) {
case 'string':
return String(value);
case 'number':
return Number(value);
case 'boolean':
return Boolean(value);
case 'date':
return new Date(value);
default:
return value;
}
}
}
// 4. Streaming Deserializer
class StreamingDeserializer {
// Chunk-based parsing
async* parseInChunks(json: string, chunkSize: number): AsyncGenerator<any> {
for (let i = 0; i < json.length; i += chunkSize) {
const chunk = json.slice(i, Math.min(i + chunkSize, json.length));
yield this.parsePartial(chunk);
}
}
// Parse JSON lines (NDJSON)
parseJSONLines(lines: string): any[] {
return lines.split('\n')
.filter(line => line.trim())
.map(line => JSON.parse(line));
}
// Parse JSON stream
async parseStream(stream: ReadableStream): Promise<any> {
const reader = stream.getReader();
let json = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
json += new TextDecoder().decode(value);
}
return JSON.parse(json);
}
private parsePartial(chunk: string): string {
// Partial parsing - just return the chunk
return chunk;
}
}
// 5. Path-Based Deserializer
class PathBasedDeserializer {
// Get value by path
getByPath<T = any>(json: string, path: string): T | null {
try {
const obj = JSON.parse(json);
const keys = path.split('.');
let value: any = obj;
for (const key of keys) {
if (value && typeof value === 'object' && key in value) {
value = value[key];
} else {
return null;
}
}
return value;
} catch (error) {
console.error('JSON parse error:', error);
return null;
}
}
// Get multiple values by paths
getMultiplePaths(json: string, paths: string[]): Record<string, any> {
const obj = JSON.parse(json);
const result: Record<string, any> = {};
for (const path of paths) {
result[path] = this.getByPathFromObject(obj, path);
}
return result;
}
// Extract nested objects
extractNested(json: string, rootPath: string): any {
try {
const obj = JSON.parse(json);
const root = this.getByPathFromObject(obj, rootPath);
if (root && typeof root === 'object') {
return root;
}
return null;
} catch (error) {
console.error('JSON parse error:', error);
return null;
}
}
private getByPathFromObject(obj: any, path: string): any {
const keys = path.split('.');
let value: any = obj;
for (const key of keys) {
if (value && typeof value === 'object' && key in value) {
value = value[key];
} else {
return null;
}
}
return value;
}
}
// 6. Secure Deserializer
class SecureDeserializer {
// Sanitize and parse
sanitizeParse<T = any>(json: string, maxDepth: number = 100): T | null {
try {
let depth = 0;
const sanitized = JSON.parse(json, (key, value) => {
depth++;
if (depth > maxDepth) {
throw new Error('Maximum depth exceeded');
}
// Remove potentially dangerous values
if (typeof value === 'function') {
return undefined;
}
return value;
});
return sanitized;
} catch (error) {
console.error('JSON parse error:', error);
return null;
}
}
// Parse with size limit
parseWithLimit<T = any>(json: string, maxSize: number): T | null {
if (json.length > maxSize) {
console.error('JSON size exceeds limit');
return null;
}
try {
return JSON.parse(json);
} catch (error) {
console.error('JSON parse error:', error);
return null;
}
}
// Parse with prototype protection
parseWithProtection<T = any>(json: string): T | null {
try {
return JSON.parse(json, (key, value) => {
// Prevent prototype pollution
if (key === '__proto__' || key === 'constructor') {
return undefined;
}
return value;
});
} catch (error) {
console.error('JSON parse error:', error);
return null;
}
}
}
// 7. Transformer Deserializer
class TransformerDeserializer {
// Parse and transform
parseAndTransform<T = any, R = any>(
json: string,
transformer: (obj: T) => R
): R | null {
try {
const obj = JSON.parse(json);
return transformer(obj);
} catch (error) {
console.error('JSON parse or transform error:', error);
return null;
}
}
// Parse with field mapping
parseWithMapping<T = any>(json: string, fieldMapping: Record<string, string>): T {
const obj = JSON.parse(json);
const result: any = {};
for (const oldKey in fieldMapping) {
const newKey = fieldMapping[oldKey];
if (oldKey in obj) {
result[newKey] = obj[oldKey];
}
}
// Copy unmapped fields
for (const key in obj) {
if (!(key in fieldMapping)) {
result[key] = obj[key];
}
}
return result;
}
// Parse with computed fields
parseWithComputed<T = any>(
json: string,
computed: Record<string, (obj: any) => any>
): T {
const obj = JSON.parse(json);
for (const key in computed) {
obj[key] = computed[key](obj);
}
return obj;
}
}
// Usage Examples
async function demonstrateJSONDeserialization() {
console.log('=== Web TypeScript JSON Deserialization Examples ===\n');
const deserializer = new JSONDeserializer();
const customDeserializer = new CustomTypeDeserializer();
const pathDeserializer = new PathBasedDeserializer();
const secureDeserializer = new SecureDeserializer();
// 1. Basic parsing
console.log('--- 1. Basic Parsing ---');
const json1 = '{ "name": "Alice", "age": 30 }';
const obj1 = deserializer.parse(json1);
console.log(obj1);
// 2. Safe parsing
console.log('\n--- 2. Safe Parsing ---');
const invalidJson = '{ invalid }';
const safeObj = deserializer.safeParse(invalidJson, { name: 'Default' });
console.log(safeObj);
// 3. Date parsing
console.log('\n--- 3. Date Parsing ---');
const json2 = '{ "date": "2024-01-15T10:30:00Z" }';
const obj2 = deserializer.parseWithDates(json2);
console.log(obj2);
// 4. Custom type deserialization
console.log('\n--- 4. Custom Type Deserialization ---');
const json3 = '{ "map": { "__type": "Map", "value": [["key", "value"]] } }';
const obj3 = customDeserializer.deserializeWithType(json3);
console.log(obj3);
// 5. Path-based access
console.log('\n--- 5. Path-Based Access ---');
const json4 = '{ "user": { "name": "Bob", "address": { "city": "NYC" } } }';
const city = pathDeserializer.getByPath(json4, 'user.address.city');
console.log(`City: ${city}`);
// 6. Secure parsing
console.log('\n--- 6. Secure Parsing ---');
const json5 = '{ "__proto__": { "polluted": true }, "data": "test" }';
const secureObj = secureDeserializer.parseWithProtection(json5);
console.log(secureObj);
console.log('\n=== All JSON Deserialization Examples Completed ===');
}
// Export functions
export { JSONDeserializer, CustomTypeDeserializer, SchemaDeserializer, StreamingDeserializer, PathBasedDeserializer, SecureDeserializer, TransformerDeserializer };
export { demonstrateJSONDeserialization };
💻 Análisis XML typescript
🟡 intermediate
⭐⭐⭐⭐
Analizar y manipular documentos XML usando DOM Parser y XPath
⏱️ 30 min
🏷️ typescript, web, serialization, xml
Prerequisites:
Intermediate TypeScript, XML, DOM API
// Web TypeScript XML Parsing Examples
// Using DOMParser, XMLSerializer, and XPath for XML processing
// 1. Basic XML Parser
class XMLParser {
private parser: DOMParser;
private serializer: XMLSerializer;
constructor() {
this.parser = new DOMParser();
this.serializer = new XMLSerializer();
}
// Parse XML string to DOM
parse(xmlString: string): XMLDocument {
const doc = this.parser.parseFromString(xmlString, 'text/xml');
// Check for parsing errors
const parserError = doc.querySelector('parsererror');
if (parserError) {
throw new Error(`XML parsing error: ${parserError.textContent}`);
}
return doc;
}
// Serialize DOM to XML string
serialize(doc: XMLDocument): string {
return this.serializer.serializeToString(doc);
}
// Parse with error handling
safeParse(xmlString: string): XMLDocument | null {
try {
return this.parse(xmlString);
} catch (error) {
console.error('XML parse error:', error);
return null;
}
}
}
// 2. XML Navigator
class XMLNavigator {
private doc: XMLDocument;
constructor(doc: XMLDocument) {
this.doc = doc;
}
// Get root element
getRoot(): Element {
return this.doc.documentElement;
}
// Get element by tag name
getElementsByTagName(tagName: string): Element[] {
const elements = this.doc.getElementsByTagName(tagName);
return Array.from(elements);
}
// Get element by ID
getElementById(id: string): Element | null {
return this.doc.getElementById(id);
}
// Get child elements
getChildren(element: Element): Element[] {
return Array.from(element.children);
}
// Get parent element
getParent(element: Element): Element | null {
return element.parentElement;
}
// Get siblings
getSiblings(element: Element): Element[] {
const parent = element.parentElement;
if (!parent) return [];
return Array.from(parent.children).filter(child => child !== element);
}
// Get next sibling
getNextSibling(element: Element): Element | null {
return element.nextElementSibling;
}
// Get previous sibling
getPreviousSibling(element: Element): Element | null {
return element.previousElementSibling;
}
}
// 3. XML Query Engine
class XMLQueryEngine {
private doc: XMLDocument;
constructor(doc: XMLDocument) {
this.doc = doc;
}
// Query with XPath
queryXPath(xpath: string): Node[] {
const result = this.doc.evaluate(
xpath,
this.doc,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
const nodes: Node[] = [];
for (let i = 0; i < result.snapshotLength; i++) {
nodes.push(result.snapshotItem(i)!);
}
return nodes;
}
// Query with XPath and get first result
queryXPathFirst(xpath: string): Node | null {
const results = this.queryXPath(xpath);
return results.length > 0 ? results[0] : null;
}
// Query with CSS selector (limited support)
querySelector(selector: string): Element | null {
return this.doc.querySelector(selector);
}
// Query all with CSS selector
querySelectorAll(selector: string): Element[] {
const elements = this.doc.querySelectorAll(selector);
return Array.from(elements);
}
// Query elements by attribute
findByAttribute(name: string, value: string): Element[] {
const xpath = `//*[@${name}='${value}']`;
return this.queryXPath(xpath) as Element[];
}
// Query elements containing text
findByText(text: string): Element[] {
const xpath = `//*[contains(text(), '${text}')]`;
return this.queryXPath(xpath) as Element[];
}
}
// 4. XML Attribute Handler
class XMLAttributeHandler {
private element: Element;
constructor(element: Element) {
this.element = element;
}
// Get attribute value
get(name: string): string | null {
return this.element.getAttribute(name);
}
// Set attribute value
set(name: string, value: string): void {
this.element.setAttribute(name, value);
}
// Remove attribute
remove(name: string): void {
this.element.removeAttribute(name);
}
// Check if attribute exists
has(name: string): boolean {
return this.element.hasAttribute(name);
}
// Get all attributes
getAll(): Record<string, string> {
const attrs: Record<string, string> = {};
for (let i = 0; i < this.element.attributes.length; i++) {
const attr = this.element.attributes[i];
attrs[attr.name] = attr.value;
}
return attrs;
}
// Get attribute names
getNames(): string[] {
return Array.from(this.element.attributes).map(attr => attr.name);
}
}
// 5. XML Content Extractor
class XMLContentExtractor {
private doc: XMLDocument;
constructor(doc: XMLDocument) {
this.doc = doc;
}
// Get text content of element
getText(element: Element): string {
return element.textContent || '';
}
// Get text content of multiple elements
getTexts(xpath: string): string[] {
const elements = this.queryElements(xpath);
return elements.map(el => this.getText(el));
}
// Get HTML content
getHTML(element: Element): string {
return element.innerHTML;
}
// Get CDATA sections
getCDATASections(element: Element): string[] {
const cdataSections: string[] = [];
const children = element.childNodes;
for (let i = 0; i < children.length; i++) {
if (children[i].nodeType === Node.CDATA_SECTION_NODE) {
cdataSections.push(children[i].textContent || '');
}
}
return cdataSections;
}
// Get comments
getComments(element: Element): string[] {
const comments: string[] = [];
const children = element.childNodes;
for (let i = 0; i < children.length; i++) {
if (children[i].nodeType === Node.COMMENT_NODE) {
comments.push(children[i].textContent || '');
}
}
return comments;
}
private queryElements(xpath: string): Element[] {
const result = this.doc.evaluate(
xpath,
this.doc,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
const elements: Element[] = [];
for (let i = 0; i < result.snapshotLength; i++) {
const node = result.snapshotItem(i);
if (node && node.nodeType === Node.ELEMENT_NODE) {
elements.push(node as Element);
}
}
return elements;
}
}
// 6. XML to JSON Converter
class XMLToJSONConverter {
private doc: XMLDocument;
constructor(doc: XMLDocument) {
this.doc = doc;
}
// Convert XML to JSON object
toJSON(rootElement?: Element): any {
const element = rootElement || this.doc.documentElement;
return this.elementToJSON(element);
}
// Convert element to JSON
private elementToJSON(element: Element): any {
const obj: any = {};
// Add attributes
if (element.attributes.length > 0) {
obj['@attributes'] = {};
for (let i = 0; i < element.attributes.length; i++) {
const attr = element.attributes[i];
obj['@attributes'][attr.name] = attr.value;
}
}
// Add child elements
const children = Array.from(element.children);
if (children.length === 0) {
// No children, use text content
obj['#text'] = element.textContent;
} else {
// Group child elements by tag name
const grouped: Record<string, Element[]> = {};
for (const child of children) {
const tagName = child.tagName;
if (!grouped[tagName]) {
grouped[tagName] = [];
}
grouped[tagName].push(child);
}
// Convert grouped children
for (const tagName in grouped) {
const elements = grouped[tagName];
if (elements.length === 1) {
obj[tagName] = this.elementToJSON(elements[0]);
} else {
obj[tagName] = elements.map(el => this.elementToJSON(el));
}
}
}
return obj;
}
// Convert to simplified JSON (no attributes or special keys)
toSimpleJSON(): any {
return this.elementToSimpleJSON(this.doc.documentElement);
}
private elementToSimpleJSON(element: Element): any {
const children = Array.from(element.children);
if (children.length === 0) {
return element.textContent;
}
const obj: any = {};
const grouped: Record<string, Element[]> = {};
for (const child of children) {
const tagName = child.tagName;
if (!grouped[tagName]) {
grouped[tagName] = [];
}
grouped[tagName].push(child);
}
for (const tagName in grouped) {
const elements = grouped[tagName];
if (elements.length === 1) {
obj[tagName] = this.elementToSimpleJSON(elements[0]);
} else {
obj[tagName] = elements.map(el => this.elementToSimpleJSON(el));
}
}
return obj;
}
}
// 7. XML Modifier
class XMLModifier {
private doc: XMLDocument;
constructor(doc: XMLDocument) {
this.doc = doc;
}
// Create new element
createElement(tagName: string, attributes?: Record<string, string>): Element {
const element = this.doc.createElement(tagName);
if (attributes) {
for (const name in attributes) {
element.setAttribute(name, attributes[name]);
}
}
return element;
}
// Append child element
appendChild(parent: Element, child: Element): void {
parent.appendChild(child);
}
// Remove element
removeElement(element: Element): void {
element.remove();
}
// Replace element
replaceElement(oldElement: Element, newElement: Element): void {
oldElement.parentNode?.replaceChild(newElement, oldElement);
}
// Clone element
cloneElement(element: Element, deep: boolean = true): Element {
return element.cloneNode(deep) as Element;
}
// Insert before
insertBefore(reference: Element, newElement: Element): void {
reference.parentNode?.insertBefore(newElement, reference);
}
// Insert after
insertAfter(reference: Element, newElement: Element): void {
reference.parentNode?.insertBefore(newElement, reference.nextSibling);
}
}
// Usage Examples
async function demonstrateXMLParsing() {
console.log('=== Web TypeScript XML Parsing Examples ===\n');
const xmlString = `
<library>
<book id="1">
<title>JavaScript Guide</title>
<author>John Doe</author>
<price>29.99</price>
</book>
<book id="2">
<title>TypeScript Basics</title>
<author>Jane Smith</author>
<price>39.99</price>
</book>
</library>
`;
// 1. Parse XML
console.log('--- 1. Parse XML ---');
const parser = new XMLParser();
const doc = parser.parse(xmlString);
console.log('XML parsed successfully');
// 2. Navigate XML
console.log('\n--- 2. Navigate XML ---');
const navigator = new XMLNavigator(doc);
const root = navigator.getRoot();
console.log(`Root element: ${root.tagName}`);
const books = navigator.getElementsByTagName('book');
console.log(`Found ${books.length} books`);
// 3. Query XML
console.log('\n--- 3. Query XML ---');
const queryEngine = new XMLQueryEngine(doc);
const titles = queryEngine.queryXPath('//library/book/title');
titles.forEach(node => {
console.log(` Title: ${node.textContent}`);
});
// 4. Attributes
console.log('\n--- 4. Attributes ---');
const firstBook = books[0];
const attrHandler = new XMLAttributeHandler(firstBook);
console.log(`Book ID: ${attrHandler.get('id')}`);
console.log('All attributes:', attrHandler.getAll());
// 5. Content extraction
console.log('\n--- 5. Content Extraction ---');
const extractor = new XMLContentExtractor(doc);
const bookTitles = extractor.getTexts('//library/book/title');
console.log('Titles:', bookTitles);
// 6. Convert to JSON
console.log('\n--- 6. Convert to JSON ---');
const converter = new XMLToJSONConverter(doc);
const json = converter.toSimpleJSON();
console.log(JSON.stringify(json, null, 2));
// 7. Modify XML
console.log('\n--- 7. Modify XML ---');
const modifier = new XMLModifier(doc);
const newBook = modifier.createElement('book', { id: '3' });
const title = modifier.createElement('title');
title.textContent = 'XML Master';
newBook.appendChild(title);
const author = modifier.createElement('author');
author.textContent = 'Bob Wilson';
newBook.appendChild(author);
root.appendChild(newBook);
const updatedXML = parser.serialize(doc);
console.log(`Updated XML has ${navigator.getElementsByTagName('book').length} books`);
console.log('\n=== All XML Parsing Examples Completed ===');
}
// Export functions
export { XMLParser, XMLNavigator, XMLQueryEngine, XMLAttributeHandler, XMLContentExtractor, XMLToJSONConverter, XMLModifier };
export { demonstrateXMLParsing };