greenter/ubl-validator
Validate OASIS UBL XML documents against the correct XSD via UBLVersionID. Provide XML content, run isValid(), and get validation errors. Supports custom XSD base directories to validate multiple UBL versions (e.g., 2.1/2.2).
Installation:
composer require greenter/ubl-validator
Basic Validation:
use Greenter\Ubl\UblValidator;
$xml = file_get_contents('invoice.xml');
$validator = new UblValidator();
if ($validator->isValid($xml)) {
// Proceed with business logic
} else {
$error = $validator->getError();
// Log or return error to user
}
First Use Case: Validate an incoming UBL invoice XML in a Laravel API endpoint:
use Greenter\Ubl\UblValidator;
public function store(Request $request) {
$validator = new UblValidator();
if (!$validator->isValid($request->xml)) {
return response()->json(['error' => $validator->getError()], 400);
}
// Process valid invoice
}
UblValidator: Core validation logic.UblPathResolver: Custom XSD directory configuration.src/xsd (default) or configurable via baseDirectory.API Request Validation:
public function validateInvoice(Request $request) {
$ublValidator = app()->make(UblValidator::class);
if (!$ublValidator->isValid($request->xml)) {
return response()->json(['error' => $ublValidator->getError()], 400);
}
return response()->json(['success' => true]);
}
File Upload Validation:
use Illuminate\Support\Facades\Storage;
use Greenter\Ubl\UblValidator;
public function handleUpload(Request $request) {
$file = $request->file('invoice');
$xml = file_get_contents($file->path());
$validator = new UblValidator();
if (!$validator->isValid($xml)) {
Storage::delete($file->path());
return back()->withErrors(['invoice' => $validator->getError()]);
}
// Save file and proceed
}
Batch Processing with Queues:
use Greenter\Ubl\UblValidator;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class ValidateUblJob implements ShouldQueue {
use InteractsWithQueue, Queueable, SerializesModels;
public $xml;
public function __construct($xml) {
$this->xml = $xml;
}
public function handle() {
$validator = new UblValidator();
if (!$validator->isValid($this->xml)) {
// Log error or notify
}
}
}
Custom XSD Directory:
$validator = new UblValidator();
$validator->pathResolver = new UblPathResolver();
$validator->pathResolver->baseDirectory = storage_path('app/xsd/ubl');
Supplier Onboarding:
supplier_validations table.E-Invoicing Compliance:
if ($validator->isValid($invoiceXml)) {
$taxAuthorityResponse = TaxAuthority::submit($invoiceXml);
}
Data Migration:
$files = Storage::disk('legacy')->files('invoices');
foreach ($files as $file) {
$xml = file_get_contents($file);
$validator->isValid($xml) ? $this->migrate($file) : $this->logError($file);
}
Laravel Service Provider:
Bind UblValidator to the container for dependency injection:
public function register() {
$this->app->bind(UblValidator::class, function () {
return new UblValidator();
});
}
Middleware for API Protection:
public function handle($request, Closure $next) {
$validator = new UblValidator();
if (!$validator->isValid($request->xml)) {
return response()->json(['error' => $validator->getError()], 400);
}
return $next($request);
}
Logging Errors:
use Illuminate\Support\Facades\Log;
if (!$validator->isValid($xml)) {
Log::error('UBL Validation Failed: ' . $validator->getError());
}
Testing: Use Laravel’s testing helpers to mock XML responses:
public function testUblValidation() {
$xml = file_get_contents(__DIR__ . '/fixtures/invoice.xml');
$validator = new UblValidator();
$this->assertTrue($validator->isValid($xml));
}
XSD Directory Structure:
/my-ubl-xsd
├── 2.1/
│ ├── common/
│ └── maindoc/
└── 2.2/
├── common/
└── maindoc/
XML Parsing Errors:
LibXML exceptions.try {
if (!$validator->isValid($xml)) {
// Handle validation error
}
} catch (\Exception $e) {
Log::error('XML Parsing Error: ' . $e->getMessage());
}
Version Mismatch:
Performance with Large XML:
Error Handling:
class UblValidationError {
public static function format(string $error): string {
return "Invalid UBL XML: " . substr($error, 0, 200) . "...";
}
}
Enable LibXML Errors:
libxml_use_internal_errors(true);
$validator->isValid($xml);
$errors = libxml_get_errors();
foreach ($errors as $error) {
echo "Error: " . $error->message . "\n";
}
libxml_clear_errors();
Check XSD Resolution:
$validator = new UblValidator();
$validator->pathResolver = new UblPathResolver();
$validator->pathResolver->baseDirectory = './custom-xsd';
Validate Against Known Good XML:
Default XSD Directory:
src/xsd, but these may not cover all UBL versions.composer.json or release notes.Case Sensitivity:
<cbc:UBLVersionID> vs. <CBC:UBLVersionID>).Namespace Handling:
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" ...>
UblValidator class to add custom error handling:
class CustomUblValidator extends UblValidator {
public function getFormattedError(): string {
$error = $this->getError();
return "Validation Failed
How can I help you explore Laravel packages today?