Skip to main content

Validation

The DDEX Builder provides comprehensive validation to ensure your XML output meets DDEX specifications and partner requirements.

Overview​

Validation occurs at multiple stages:

  • Preflight validation: Before building begins
  • Structure validation: During XML construction
  • Schema validation: Against DDEX XSD schemas
  • Partner validation: Using partner-specific rules

Preflight Validation​

Validate your data before building to catch errors early:

import { DdexBuilder, ValidationLevel } from 'ddex-builder';

const builder = new DdexBuilder();
const data = { /* your release data */ };

// Comprehensive validation
const validation = await builder.validate(data, {
level: ValidationLevel.STRICT,
includeWarnings: true,
partnerPreset: 'spotify'
});

if (!validation.isValid) {
console.log('Validation errors:');
validation.errors.forEach(error => {
console.log(`- ${error.path}: ${error.message}`);
});

console.log('Warnings:');
validation.warnings.forEach(warning => {
console.log(`- ${warning.path}: ${warning.message}`);
});
}

Validation Levels​

Basic Validation​

from ddex_builder import DdexBuilder, ValidationLevel

builder = DdexBuilder()

# Basic validation - required fields only
result = builder.validate(data, level=ValidationLevel.BASIC)

Standard Validation​

// Standard validation - DDEX specification compliance
const result = await builder.validate(data, {
level: ValidationLevel.STANDARD,
version: '4.3'
});

Strict Validation​

# Strict validation - all rules + best practices
result = builder.validate(data,
level=ValidationLevel.STRICT,
enforce_best_practices=True
)

Partner-Specific Validation​

Validate against partner requirements:

// Spotify validation
const spotifyValidation = await builder.validate(data, {
partnerPreset: 'spotify',
includeMetadataChecks: true
});

// YouTube Music validation
const youtubeValidation = await builder.validate(data, {
partnerPreset: 'youtube',
requireTerritoryInfo: true
});

// Apple Music validation
const appleValidation = await builder.validate(data, {
partnerPreset: 'apple',
enforceIsrcFormat: true
});

Custom Validation Rules​

Add your own validation logic:

from ddex_builder import DdexBuilder, ValidationRule

class CustomISRCRule(ValidationRule):
def validate(self, data):
errors = []
for track in data.get('tracks', []):
isrc = track.get('isrc')
if isrc and not self.is_valid_isrc(isrc):
errors.append({
'path': f'tracks[{track["id"]}].isrc',
'message': f'Invalid ISRC format: {isrc}',
'severity': 'error'
})
return errors

def is_valid_isrc(self, isrc):
# Your custom ISRC validation logic
return len(isrc) == 12 and isrc[:2].isalpha()

builder = DdexBuilder()
builder.add_validation_rule(CustomISRCRule())

result = builder.validate(data)

Field-Level Validation​

Required Fields​

const validation = await builder.validate(data);

// Check specific field requirements
if (validation.missingRequired.length > 0) {
console.log('Missing required fields:');
validation.missingRequired.forEach(field => {
console.log(`- ${field.path}: ${field.description}`);
});
}

Data Type Validation​

# Automatic type checking
data = {
'title': 123, # Should be string
'duration': 'invalid', # Should be number
'release_date': '2023-13-45' # Invalid date
}

result = builder.validate(data)
for error in result.type_errors:
print(f"{error.path}: expected {error.expected_type}, got {error.actual_type}")

Format Validation​

use ddex_builder::{DdexBuilder, ValidationOptions};

let options = ValidationOptions {
validate_isrc_format: true,
validate_upc_format: true,
validate_territory_codes: true,
validate_language_codes: true,
validate_currencies: true,
};

let result = builder.validate_with_options(&data, options)?;

Territory and Language Validation​

const validation = await builder.validate(data, {
validateTerritories: true,
validateLanguages: true,
allowedTerritories: ['US', 'GB', 'DE'], // Restrict territories
requireLanguageForLyrics: true
});

// Check territory-specific errors
validation.territoryErrors.forEach(error => {
console.log(`Territory error: ${error.territory} - ${error.message}`);
});

Validation During Build​

Enable validation during the build process:

builder = DdexBuilder(
validate_on_build=True,
validation_level=ValidationLevel.STANDARD,
fail_on_warnings=False
)

try:
xml = builder.build(data)
print("Build successful with validation")
except ValidationError as e:
print(f"Validation failed: {e.message}")
for error in e.errors:
print(f" - {error.path}: {error.message}")

Batch Validation​

Validate multiple releases efficiently:

const releases = [/* array of release data */];

const batchValidation = await builder.validateBatch(releases, {
parallel: true,
stopOnFirstError: false,
includeValidReleases: true
});

console.log(`Valid: ${batchValidation.valid.length}`);
console.log(`Invalid: ${batchValidation.invalid.length}`);

// Process valid releases
const validXml = await builder.buildBatch(batchValidation.valid);

Error Categories​

Critical Errors​

  • Missing required fields
  • Invalid data types
  • Schema violations
  • Partner requirement violations

Warnings​

  • Missing recommended fields
  • Suboptimal formats
  • Best practice violations
  • Performance concerns

Info Messages​

  • Suggestions for improvement
  • Alternative approaches
  • Additional metadata opportunities

Validation Reports​

Generate detailed validation reports:

validation = builder.validate(data, include_suggestions=True)

# Generate HTML report
report_html = validation.to_html_report()
with open('validation_report.html', 'w') as f:
f.write(report_html)

# Generate JSON report for API integration
report_json = validation.to_json()

# Generate CSV for spreadsheet analysis
report_csv = validation.to_csv()

Configuration​

Customize validation behavior:

const builder = new DdexBuilder({
validation: {
enabledRules: [
'required-fields',
'data-types',
'isrc-format',
'territory-codes'
],
customRules: [
new MyCustomRule(),
new AnotherRule()
],
errorThreshold: 10, // Stop after 10 errors
warningThreshold: 50, // Stop after 50 warnings
treatWarningsAsErrors: false
}
});

Performance Considerations​

Validation performance tips:

  1. Use appropriate validation levels - Basic for development, Strict for production
  2. Enable parallel validation for batch processing
  3. Cache validation results for repeated builds
  4. Disable unused rules to improve performance
  5. Use incremental validation for large datasets

Best Practices​

  1. Validate early and often - Don't wait until build time
  2. Use partner presets when targeting specific platforms
  3. Implement custom rules for organization-specific requirements
  4. Monitor validation metrics to identify common issues
  5. Provide clear error messages to help users fix issues
  6. Version your validation rules along with your data schemas

Common Validation Patterns​

Pre-submission Validation​

async function validateForSubmission(releaseData, targetPartner) {
const validation = await builder.validate(releaseData, {
level: ValidationLevel.STRICT,
partnerPreset: targetPartner,
includeMetadataQuality: true
});

if (!validation.isValid) {
throw new Error(`Release not ready for ${targetPartner}: ${validation.summary}`);
}

return validation;
}

Automated Quality Checks​

def automated_quality_check(releases):
builder = DdexBuilder()
results = []

for release in releases:
validation = builder.validate(release,
level=ValidationLevel.STANDARD,
include_quality_score=True
)

results.append({
'id': release['id'],
'valid': validation.is_valid,
'quality_score': validation.quality_score,
'recommendations': validation.recommendations
})

return results