PHPackages                             friendsofcxml/cxml-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. friendsofcxml/cxml-php

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

friendsofcxml/cxml-php
======================

PHP Implementation of cXML Standard

2.2.1(6mo ago)16100.6k↑10.9%61MITPHPPHP &gt;= 8.2 &lt; 8.5CI passing

Since May 19Pushed 2mo ago3 watchersCompare

[ Source](https://github.com/FriendsOfCXML/cxml-php)[ Packagist](https://packagist.org/packages/friendsofcxml/cxml-php)[ RSS](/packages/friendsofcxml-cxml-php/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (17)Versions (46)Used By (1)

What is it?
===========

[](#what-is-it)

> cXML is a streamlined protocol intended for consistent communication of business documents between procurement applications, e-commerce hubs and suppliers.
>
> cXML Reference Guide (PDF):

Getting Started
===============

[](#getting-started)

Installation
------------

[](#installation)

```
$ composer require friendsofcxml/cxml-php
```

Then include Composer’s autoloader:

```
require_once 'vendor/autoload.php';
```

Get current dtd definition files
--------------------------------

[](#get-current-dtd-definition-files)

1. Download get current Specification from
2. Extract files
3. Use cXML.dtd for validation (see below)

Quickstart
----------

[](#quickstart)

### Identity and credentials

[](#identity-and-credentials)

```
//we use a basic registry here. You could use your own (db-based?) repository that implements CredentialRepositoryInterface
$credentialRegistry = new \CXml\Credential\Registry();

$someSupplier = new \CXml\Model\Credential('DUNS', 12345);
$credentialRegistry->registerCredential($someSupplier);

$someBuyer = new \CXml\Model\Credential('my-id-type', "buyer@domain.com");
$credentialRegistry->registerCredential($someBuyer);

$someHub = new \CXml\Model\Credential('my-id-type', "hub@domain.com", "abracadabra");
$credentialRegistry->registerCredential($someHub);
```

### Register Handler

[](#register-handler)

```
$handlerRegistry = new \CXml\Handler\HandlerRegistry();

$handlerRegistry->register(new CXml\Handler\Request\SelfAwareProfileRequestHandler(...));
$handlerRegistry->register(new CXml\Handler\Request\StaticStartPagePunchOutSetupRequestHandler(...));
$handlerRegistry->register(new MyOrderRequestHandler());
$handlerRegistry->register(new MyStatusUpdateRequestHandler());
...
```

### Build cXML

[](#build-cxml)

```
//$payload = new \CXml\Model\Message\...Message(...);
//or...
//$payload = new \CXml\Model\Request\...Request(...);
//or...
$payload = new \CXml\Model\Response\...Response(...);

$cXml = \CXml\Builder::create()
    ->payload($payload)
    ->build();

$payload = new \CXml\Model\Request\...Request(...);
$cXml = \CXml\Builder::create()
    ->payload($payload)
    ->from(...)
    ->to(...)
    ->sender(...)
    ->build();
```

### Register outgoing cXML documents

[](#register-outgoing-cxml-documents)

You may want to register sent-out documents so they can be referenced by subsequent request-documents via payloadId.

```
$documentRegistory = new MyDocumentRegistry(); //implements CXml\Document\DocumentRegistryInterface

$documentRegistory->register($cXml);
```

### Process incoming cXML documents

[](#process-incoming-cxml-documents)

```
$headerProcessor = new \CXml\Processor\HeaderProcessor($credentialRegistry, $credentialRegistry);

$cXmlProcessor = new \CXml\Processor\Processor(
  $headerProcessor,
  $handlerRegistry,
  $builder
);

$cXmlProcessor->process($cXml);
```

### Putting it all together

[](#putting-it-all-together)

```
$credentialRegistry = new \CXml\Credential\Registry();
//TODO register credentials...

$handlerRegistry = new \CXml\Handler\HandlerRegistry();
//TODO register handler...

$builder = \CXml\Builder::create();

$headerProcessor = new \CXml\Processor\HeaderProcessor($credentialRegistry, $credentialRegistry);
$cXmlProcessor = new \CXml\Processor\Processor(
  $headerProcessor,
  $handlerRegistry,
  $builder
);

$pathToDtd = '.'; //point the directory with extracted contents of zip-file with the DTDs, downloaded from cxml.org
$dtdValidator = \CXml\Validation\DtdValidator::fromDtdDirectory($pathToDtd);
$serializer = \CXml\Serializer::create();

$endpoint = new \CXml\Endpoint(
    $serializer,
    $dtdValidator,
    $cXmlProcessor
);

//$xmlString could be the body of an incoming http request
$xmlString = '...';
$result = $endpoint->parseAndProcessStringAsCXml($xmlString);

//$result could be null (i.e. for a Response or Message) or another CXml object which would be the Response to a Request
//you would have to handle the transport yourself
```

### Handling Date vs DateTime

[](#handling-date-vs-datetime)

The cXML specification is not perfectly clear about the format of dates and times. The specification says that dates should be formatted "in the restricted subset of ISO 8601". That means that the format could either be a full ISO 8601 format with time and timezone information (i.e. 2015-04-14T13:36:00-08:00) or a format without time and timezone (2015-04-14).

With some fields the actual time of day is not relevant and could lead to confusion. For example, the `requestedDeliveryDate` field in `ItemOut`. Real-world experience shows that here it is common to only specify the date. Althout one could argue that the time of day is still relevant here for real tight on-point deliveries.

To solve this problem we introduced a determined `CXml\Model\Date` class in case of using an explicit date (without time). This class extends `DateTime` and is therefore compatible with the rest of the model. The class enforces a date-only representation (Y-m-d).

#### Serialization

[](#serialization)

You should use the `CXml\Model\Date` class when generating your object-graph in cases you want to output a date-only value.

#### Deserialization

[](#deserialization)

When parsing a date-property from a cXML document, the `CXml\Model\Date` will be instantiated **if** a date-only value was discovered (Y-m-d).

Extending cXML
--------------

[](#extending-cxml)

### Add custom elements

[](#add-custom-elements)

The definition of cXML is open for extension. There are ways to extend the DTD with overriding existing variables and therefore adding custom elements. With version 2.1.0 we introduced a way to add custom elements to the cXML model.

To make this happen, we have to build our own DTD file and import the original DTD file in it. We can then add our own elements and attributes in the variables that are defined in the original DTD file.

TODO this is only really implemented for the Payment node at the moment.

#### Example

[](#example)

An example of a custom DTD file that adds a custom element to the `PaymentReference` element:

```

%elements;

```

To use this DTD file for validation as well as for serialization and deserialization, you could save the file next to the other DTD files from cXML and use `DtdValidator::fromDtdDirectory` just as you would with the original DTD files. Or you could explicitly load only the new DTD file with `new DtdValidator($arrayOfDtdFilepaths)`.

Also you would probably want newly generated cXML files to point to your DTD file. You can do this by telling the serializer to use your DTD file: `Serializer::create('http://...publicUrlToYourDtd')`.

Now the new element also has to be known by the serializer. Usually the model classes can be found in `CXml\Model`.

###  Health Score

59

—

FairBetter than 99% of packages

Maintenance77

Regular maintenance activity

Popularity43

Moderate usage in the ecosystem

Community24

Small or concentrated contributor base

Maturity78

Established project with proven stability

 Bus Factor1

Top contributor holds 73% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~29 days

Recently: every ~53 days

Total

43

Last Release

206d ago

Major Versions

0.3.0 → 1.0.02022-06-15

1.12 → 2.0RC12024-09-11

PHP version history (4 changes)0.1.0PHP ^8.0

0.2.0PHP ^7.4 || ^8.0

2.0RC1PHP ^8.2

2.2.0PHP &gt;= 8.2 &lt; 8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/f43eab03b75d378f445dcd83583602bfbd44d7ff88faeefa8f3c79b6b1779b6a?d=identicon)[mathielen](/maintainers/mathielen)

![](https://www.gravatar.com/avatar/35ae9f649186119f3e44ca1f91ff9f44b13e54461944a65744e3edc9fb273d28?d=identicon)[ynnoig](/maintainers/ynnoig)

---

Top Contributors

[![mathielen](https://avatars.githubusercontent.com/u/1571485?v=4)](https://github.com/mathielen "mathielen (216 commits)")[![ynnoig](https://avatars.githubusercontent.com/u/22853912?v=4)](https://github.com/ynnoig "ynnoig (59 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (6 commits)")[![faaru-io](https://avatars.githubusercontent.com/u/52386126?v=4)](https://github.com/faaru-io "faaru-io (6 commits)")[![Rike-cz](https://avatars.githubusercontent.com/u/4247582?v=4)](https://github.com/Rike-cz "Rike-cz (4 commits)")[![wehrsefr](https://avatars.githubusercontent.com/u/166113834?v=4)](https://github.com/wehrsefr "wehrsefr (2 commits)")[![M-arcus](https://avatars.githubusercontent.com/u/25648755?v=4)](https://github.com/M-arcus "M-arcus (1 commits)")[![jeromegxj](https://avatars.githubusercontent.com/u/90626198?v=4)](https://github.com/jeromegxj "jeromegxj (1 commits)")[![isybuy](https://avatars.githubusercontent.com/u/157586129?v=4)](https://github.com/isybuy "isybuy (1 commits)")

---

Tags

cxmlxmldataedie-commercecommercecxmlpunchoutorder-request

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/friendsofcxml-cxml-php/health.svg)

```
[![Health](https://phpackages.com/badges/friendsofcxml-cxml-php/health.svg)](https://phpackages.com/packages/friendsofcxml-cxml-php)
```

###  Alternatives

[jms/serializer-bundle

Allows you to easily serialize, and deserialize data of any complexity

1.8k89.3M627](/packages/jms-serializer-bundle)[goetas-webservices/xsd2php

Convert XSD (XML Schema) definitions into PHP classes and JMS metadata

2411.6M37](/packages/goetas-webservices-xsd2php)[goetas-webservices/xsd2php-runtime

Convert XSD (XML Schema) definitions into PHP classes

4910.9M36](/packages/goetas-webservices-xsd2php-runtime)[amabnl/amadeus-ws-client

SOAP Web Service client library for interacting with the Amadeus GDS through its SOAP interface

204248.5k](/packages/amabnl-amadeus-ws-client)[easybill/e-invoicing

A package to read and create EN16931 e-invoices or CIUS like: XRechnung, ZUGFeRD etc.

12122.5k](/packages/easybill-e-invoicing)[crwlr/schema-org

Extract schema.org structured data from HTML documents.

1519.9k1](/packages/crwlr-schema-org)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
