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

sabre/xml

sabre/xml is a specialized PHP library for reading and writing XML. It offers a flexible reader/writer API with good namespace support, modern type declarations in v3, and compatibility with PHP 7.4 and 8 for building reliable XML-based integrations.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sabre/xml
    

    Ensure your composer.json targets PHP 8.2+ (for v4.x) or PHP 7.4+ (for v3.x).

  2. First Use Case: Parse a simple XML string into an associative array:

    use Sabre\Xml\Reader;
    
    $reader = new Reader();
    $reader->parse('<root><user><name>John</name><email>john@example.com</email></user></root>');
    $data = $reader->getParsedData();
    // Output: ['user' => ['name' => 'John', 'email' => 'john@example.com']]
    
  3. Where to Look First:


Implementation Patterns

Core Workflows

1. Parsing XML with Custom Logic

Use the Reader class with deserializers for complex data:

$reader = new Reader();
$reader->parse('<order><items><item id="101">Laptop</item></items></order>');

// Register a custom deserializer for 'item' elements
$reader->addDeserializer('item', function ($element) {
    return [
        'id' => $element['@id'],
        'name' => $element['#text']
    ];
});

$orders = $reader->getParsedData();
// Output: ['order' => ['items' => [['id' => '101', 'name' => 'Laptop']]]]

2. Generating XML from Arrays

Leverage the Writer for structured XML output:

use Sabre\Xml\Writer;

$writer = new Writer();
$writer->write('<users>', [
    'user' => [
        ['name' => 'Alice', 'role' => 'admin'],
        ['name' => 'Bob', 'role' => 'user']
    ]
]);
echo $writer->getXmlString();
// Output: <users><user><name>Alice</name><role>admin</role></user>...</users>

3. Service Class for Round-Trips

Use Service to parse and rewrite XML in one step:

use Sabre\Xml\Service;

$service = new Service();
$service->parse('<config><database>mysql</database></config>');
$data = $service->getParsedData(); // Parse
$service->write('<new_config>', $data); // Rewrite

4. Laravel Integration

Wrap the library in a service provider or facade for consistency:

// app/Providers/SabreXmlServiceProvider.php
namespace App\Providers;
use Sabre\Xml\Reader;
use Illuminate\Support\ServiceProvider;

class SabreXmlServiceProvider extends ServiceProvider {
    public function register() {
        $this->app->singleton('sabre.xml.reader', function () {
            return new Reader();
        });
    }
}

Register in config/app.php and inject via Laravel’s DI:

$reader = app('sabre.xml.reader');

5. Handling Namespaces

Use parseClarkNotation for namespace-aware parsing:

$reader = new Reader();
$reader->parse('<ns:root xmlns:ns="http://example.com/ns"><ns:item>Value</ns:item></ns:root>');
$data = $reader->parseClarkNotation('ns:item');

6. Error Handling

Catch Sabre\Xml\Exception for malformed XML:

try {
    $reader->parse('<invalid>xml</invalid>');
} catch (\Sabre\Xml\Exception $e) {
    report($e); // Log via Laravel's error handler
}

Integration Tips

  1. Validation: Combine with Laravel’s Validator for schema validation:

    use Illuminate\Support\Facades\Validator;
    
    $data = $reader->getParsedData();
    $validator = Validator::make($data, [
        'user.name' => 'required|string',
        'user.email' => 'required|email'
    ]);
    
  2. Caching: Cache parsed XML responses (e.g., for SOAP APIs):

    $cacheKey = 'soap_response_' . md5($request->getContent());
    $data = Cache::remember($cacheKey, now()->addHours(1), function () use ($reader) {
        return $reader->parse($request->getContent())->getParsedData();
    });
    
  3. Testing: Use Laravel’s XmlReader mocks in PHPUnit:

    $mockReader = $this->createMock(\Sabre\Xml\Reader::class);
    $mockReader->method('getParsedData')->willReturn(['test' => 'data']);
    $this->app->instance('sabre.xml.reader', $mockReader);
    
  4. SOAP Integration: Pair with php-soap for SOAP services:

    $client = new \SoapClient($wsdl);
    $response = $client->__doRequest($xml, $location, $action, $version);
    $reader = new Reader();
    $reader->parse($response);
    

Gotchas and Tips

Pitfalls

  1. Closed Resource Handling:

    • Issue: Passing a closed stream/resource to parse() or expect() throws an exception.
    • Fix: Reopen the resource or use fopen()/tmpfile():
      $resource = fopen('php://temp', 'r+');
      fwrite($resource, $xmlString);
      rewind($resource);
      $reader->parse($resource);
      
  2. Namespace Quirks:

    • Issue: Elements from foreign namespaces may not appear in getParsedData() by default.
    • Fix: Use parseClarkNotation() or enable namespace handling:
      $reader->setNamespaceHandling(true);
      
  3. Empty XML Elements:

    • Issue: Empty elements (e.g., <tag></tag>) may cause infinite loops in older versions.
    • Fix: Upgrade to v2.2.1+ or explicitly handle empty nodes:
      $reader->addDeserializer('empty_tag', function () {
          return null; // Explicitly return null for empty tags
      });
      
  4. Type Declarations (v3+):

    • Issue: Extending classes in v3 requires type hints for parameters/returns.
    • Fix: Update your code to match Sabre’s type signatures:
      class CustomReader extends \Sabre\Xml\Reader {
          public function customParse(string $xml): array {
              return $this->parse($xml)->getParsedData();
          }
      }
      
  5. PHP 8.2+ Compatibility:

    • Issue: Some methods may throw TypeError if not using v4.x.
    • Fix: Pin to sabre/xml:^4.0 in composer.json for PHP 8.2+:
      "require": {
          "sabre/xml": "^4.0"
      }
      

Debugging Tips

  1. Enable Verbose Errors: Configure libxml for detailed error messages:

    libxml_use_internal_errors(true);
    $reader->parse($xml);
    $errors = libxml_get_errors();
    foreach ($errors as $error) {
        report("XML Error: {$error->message}");
    }
    libxml_clear_errors();
    
  2. Inspect Parsed Structure: Use debug() to dump the parsed data:

    $data = $reader->getParsedData();
    \Illuminate\Support\Facades\Log::debug('Parsed XML:', $data);
    
  3. Check for Malformed XML: Validate XML before parsing:

    if (!\Sabre\Xml\Reader::isValidXml($xmlString)) {
        throw new \InvalidArgumentException('Invalid XML provided.');
    }
    

Extension Points

  1. Custom Deserializers: Extend functionality by adding deserializers for domain-specific XML:
    $reader->addDeserializer('invoice', function ($element) {
        return [
            'amount' => (float) $element['@amount'],
            'currency' => $element['@currency'],
            'items' => array_map(function ($item) {
                return ['product' => $item['#text'],
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope