Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Xml Laravel Package

thenorthmemory/xml

Lightweight XML transformer for PHP: parse XML into arrays and build XML back from arrays. Supports repeated elements/lists, optional pretty printing, custom root nodes, and wrapping arrays to control tag output. Extracted from wechatpay-php for general use.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package via Composer:

composer require thenorthmemory/xml

First Use Case: Convert an XML string to an array for processing:

use TheNorthMemory\Xml\Transformer;

// Parse XML to array
$xml = '<xml><hello>world</hello></xml>';
$data = Transformer::toArray($xml);

// Build array back to XML
$newXml = Transformer::toXml($data);

Where to Look First:

  • README.md for basic usage examples.
  • API section in the package docs for method signatures.
  • Test cases in the repository for edge-case handling (e.g., repeated tags).

Implementation Patterns

Core Workflows

1. Parsing XML Responses (APIs/Legacy Systems)

// In a Laravel service or controller
public function handleXmlResponse(string $xmlPayload): array
{
    return Transformer::toArray($xmlPayload);
}

// Usage in a controller
public function processPaymentGatewayResponse(Request $request)
{
    $xmlResponse = $request->getContent();
    $data = Transformer::toArray($xmlResponse);
    // Process $data (e.g., save to DB, return to client)
}

2. Building XML Requests

// Generate XML for a third-party API
public function buildPaymentRequest(array $paymentData): string
{
    return Transformer::toXml(
        $paymentData,
        headless: false, // Include root tag
        indent: true,    // Pretty-print
        root: 'PaymentRequest'
    );
}

3. Handling Repeated Tags

// Parse XML with repeated <item> tags
$xml = '<root><items><item>1</item><item>2</item></items></root>';
$data = Transformer::toArray($xml);
// $data['items']['item'] = ['1', '2'] (array of values)

// Rebuild with custom item tag
$data['items'] = Transformer::wrap($data['items']['item'], true, 'customItem');
$xml = Transformer::toXml($data, false, true, 'root');

Integration Tips

  • Laravel Facade (Optional): Create a facade for cleaner syntax:

    // app/Providers/AppServiceProvider.php
    use Illuminate\Support\Facades\Facade;
    use TheNorthMemory\Xml\Transformer;
    
    class AppServiceProvider extends ServiceProvider {
        public function boot() {
            Facade::register('Xml', function () {
                return new Transformer();
            });
        }
    }
    

    Usage:

    $data = Xml::toArray($xml);
    
  • Service Container Binding: Bind the transformer to Laravel’s container for dependency injection:

    $this->app->bind('xml.transformer', function () {
        return new Transformer();
    });
    
  • Request/Response Macros: Extend Laravel’s Request or Response classes to auto-parse/build XML:

    // app/Http/Requests/XmlRequest.php
    use TheNorthMemory\Xml\Transformer;
    
    class XmlRequest extends FormRequest {
        public function getXmlData(): array
        {
            return Transformer::toArray($this->getContent());
        }
    }
    
  • Form Request Validation: Validate XML structure before processing:

    public function rules()
    {
        return [
            'xml_data' => 'required|string',
        ];
    }
    
    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            $xml = $this->input('xml_data');
            try {
                $data = Transformer::toArray($xml);
                // Add custom validation logic on $data
            } catch (\Exception $e) {
                $validator->errors()->add('xml_data', 'Invalid XML format');
            }
        });
    }
    
  • Artisan Commands: Use the transformer in CLI tools for bulk XML processing:

    // app/Console/Commands/ProcessXmlFiles.php
    use TheNorthMemory\Xml\Transformer;
    
    class ProcessXmlFiles extends Command {
        protected $signature = 'xml:process {path}';
        public function handle() {
            $files = File::files($this->argument('path'));
            foreach ($files as $file) {
                $xml = File::get($file);
                $data = Transformer::toArray($xml);
                // Process $data (e.g., save to DB)
            }
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Repeated Tags Without wrap(): XML like <root><item>1</item><item>2</item></root> becomes:

    ['item' => ['1', '2']] // Not nested under 'root'
    

    Fix: Use Transformer::wrap() to control the structure:

    $data['item'] = Transformer::wrap($data['item'], true, 'item');
    
  2. Headless XML Output: Transformer::toXml() defaults to headless: true, omitting the root tag. Set headless: false to include it:

    $xml = Transformer::toXml($data, headless: false);
    
  3. Attribute Handling: The package does not parse XML attributes by default. Use SimpleXML or DOMDocument for attribute-heavy XML:

    // Fallback for attributes
    $simpleXml = simplexml_load_string($xml);
    $attributes = $simpleXml->attributes();
    
  4. Namespace Support: The transformer ignores XML namespaces. For namespaced XML, pre-process with SimpleXML:

    $xml = simplexml_load_string($xml);
    $xml->registerXPathNamespace('ns', 'http://example.com/ns');
    
  5. Malformed XML: Transformer::toArray() may throw cryptic errors for invalid XML. Sanitize input first:

    $sanitizedXml = Transformer::sanitize($xml);
    $data = Transformer::toArray($sanitizedXml);
    
  6. Large XML Files: The package loads XML into memory. For files >10MB, use XMLReader or chunked processing:

    $reader = new XMLReader();
    $reader->open($filePath);
    while ($reader->read()) {
        if ($reader->nodeType === XMLReader::ELEMENT) {
            // Process nodes incrementally
        }
    }
    
  7. PHP Warnings: Suppress libxml warnings (e.g., for invalid characters) with:

    libxml_use_internal_errors(true);
    $data = Transformer::toArray($xml);
    libxml_clear_errors();
    

Debugging Tips

  • Validate XML Structure: Use Transformer::toArray() + print_r() to inspect parsed data:

    $data = Transformer::toArray($xml);
    print_r($data);
    
  • Pretty-Print XML: Enable indentation for debugging:

    $xml = Transformer::toXml($data, indent: true);
    
  • Compare Outputs: Test against known-good XML/array pairs to catch regressions:

    $expectedArray = ['key' => 'value'];
    $actualArray = Transformer::toArray($xml);
    $this->assertEquals($expectedArray, $actualArray);
    
  • Log Transformations: Log XML ↔ array conversions for auditing:

    \Log::debug('XML Parsed', ['xml' => $xml, 'data' => $data]);
    

Extension Points

  1. Custom Wrapping Logic: Extend LabeledArrayIterator for custom array-to-XML mapping:

    class CustomArrayIterator extends \TheNorthMemory\Xml\LabeledArrayIterator {
        public function current(): string {
            return '<custom>' . parent::current() . '</custom>';
        }
    }
    
  2. Pre/Post-Processing: Wrap Transformer methods in Laravel middleware or decorators:

    class XmlTransformerDecorator {
        public function parse(string $xml): array {
            $sanitized = Transformer::sanitize($xml);
            return Transformer::toArray($sanitized);
        }
    }
    
  3. Event Listeners: Trigger events before/after XML transformations:

    // app/Providers/EventServiceProvider.php
    protected $listen = [
        'xml.parsing' => [
            \App\Listeners\LogXmlParsing::class,
        ],
    ];
    
  4. Testing Helpers: Create a test trait for XML assertions:

    // tests/TestCase.php
    use function TheNorthMemory\Xml\Transformer;
    
    trait XmlAssertions {
        protected function assertXmlEquals(string $expectedXml, array $data): void {
            $actualXml = Transformer::toXml($data);
            $this->assertXmlStringEqualsXmlString($expectedXml, $actualXml);
        }
    }
    

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor