xsd2php
Convert XSD into PHP classes.
With goetas-webservices/xsd2php
you can convert any XSD/WSDL definition into PHP classes.
XSD2PHP can also generate JMS Serializer compatible metadata that can be used to serialize/unserialize the object instances.
Installation
There is one recommended way to install xsd2php via Composer:
- adding the dependency to your
composer.json
file:
"require": {
..
"goetas-webservices/xsd2php-runtime":"^0.2.2",
..
},
"require-dev": {
..
"goetas-webservices/xsd2php":"^0.3",
..
},
Usage
With this example we will convert OTA XSD definitions into PHP classes.
Suppose that you have all XSD files in /home/my/ota
, first of all we need a configuration file
(as example config.yml
) that will keep all the namespace and directory mappings information.
# config.yml
# Linux Users: PHP Namespaces use back slash \ rather than a forward slash /
# So for destinations_php, the namespace would be TestNs\MyApp
xsd2php:
namespaces:
'http://www.example.org/test/': 'TestNs\MyApp'
destinations_php:
'TestNs\MyApp': soap/src
# 'TestNs\MyApp': soap\src # on Windows
destinations_jms:
'TestNs\MyApp': soap/metadata
# 'TestNs\MyApp': soap\metadata # on Windows
# Uncomment this section if you want to have also symfony/validator metadata to be generated from XSD
# destinations_validation:
# 'TestNs\MyApp': soap/validation
# 'TestNs\MyApp': soap\validation # on Windows
aliases: # optional
'http://www.example.org/test/':
MyCustomXSDType: 'MyCustomMappedPHPType'
naming_strategy: short # optional and default
path_generator: psr4 # optional and default
# known_locations: # optional
# "http://www.example.org/test/somefile.xsd": somefile.xsd
# known_namespace_locations: # optional
# "urn:veloconnect:catalog-1.1": xsd/catalog-1.1.xsd
Here is an explanation on the meaning of each parameter:
-
xsd2php.namespaces
(required) defines the mapping between XML namespaces and PHP namespaces. (in the example we have thehttp://www.example.org/test/
XML namespace mapped toTestNs\MyApp
) -
xsd2php.destinations_php
(required) specifies the directory where to save the PHP classes that belongs toTestNs\MyApp
PHP namespace. (in this exampleTestNs\MyApp
classes will be saved intosoap/src
directory. -
xsd2php.destinations_jms
(required) specifies the directory where to save JMS Serializer metadata files that belongs toTestNs\MyApp
PHP namespace. (in this exampleTestNs\MyApp
metadata will be saved intosoap/metadata
directory. -
xsd2php.aliases
(optional) specifies some mappings that are handled by custom JMS serializer handlers. Allows to specify to do not generate metadata for some XML types, and assign them directly a PHP class. For that PHP class is necessary to create a custom JMS serialize/deserialize handler. -
xsd2php.naming_strategy
(optional) specifies the naming strategy to use when converting XML names PHP classes. -
xsd2php.path_generator
(optional) specifies the strategy to use for path generation and file saving -
xsd2php.known_locations
(optional) override remote location with a local file. -
xsd2php.known_namespace_locations
(optional) Specify schema location by namespace. This can be used to read schemas which import namespaces but do not specify schemaLocation attributes.
Generate PHP classes and JMS metadata info
vendor/bin/xsd2php convert config.yml /home/my/ota/OTA_Air*.xsd
This command will generate PHP classes and JMS metadata files for all the XSD files matching /home/my/ota/OTA_Air*.xsd
and using the configuration available in config.yml
Serialize / Unserialize
XSD2PHP can also generate for you JMS Serializer metadata that you can use to serialize/unserialize the generated PHP class instances.
The parameter aliases
in the configuration file, will instruct XSD2PHP to not generate any metadata information or
PHP class for the {http://www.example.org/test/}MyCustomXSDType
type.
All reference to this type are replaced with the MyCustomMappedPHPType
name.
You have to provide a custom serializer for this type/alis.
Here is an example on how to configure JMS serializer to handle custom types
<?php
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\Handler\HandlerRegistryInterface;
use GoetasWebservices\Xsd\XsdToPhpRuntime\Jms\Handler\BaseTypesHandler;
use GoetasWebservices\Xsd\XsdToPhpRuntime\Jms\Handler\XmlSchemaDateHandler;
$serializerBuilder = SerializerBuilder::create();
$serializerBuilder->addMetadataDir('metadata dir', 'TestNs');
$serializerBuilder->configureHandlers(function (HandlerRegistryInterface $handler) use ($serializerBuilder) {
$serializerBuilder->addDefaultHandlers();
$handler->registerSubscribingHandler(new BaseTypesHandler()); // XMLSchema List handling
$handler->registerSubscribingHandler(new XmlSchemaDateHandler()); // XMLSchema date handling
// $handler->registerSubscribingHandler(new YourhandlerHere());
});
$serializer = $serializerBuilder->build();
// deserialize the XML into Demo\MyObject object
$object = $serializer->deserialize('<some xml/>', 'TestNs\MyObject', 'xml');
// some code ....
// serialize the Demo\MyObject back into XML
$newXml = $serializer->serialize($object, 'xml');
Validation
<?php
use Symfony\Component\Validator\Validation;
// get the validator
$builder = Validation::createValidatorBuilder();
foreach (glob('soap/validation/*.yml') as $file) {
$builder->addYamlMapping($file);
}
$validator = $builder->getValidator();
// validate $object
$violations = $validator->validate($object, null, ['xsd_rules']);
xsd:anyType
or xsd:anySimpleType
Dealing with If your XSD contains xsd:anyType
or xsd:anySimpleType
types you have to specify a handler for this.
When you generate the JMS metadata you have to specify a custom handler:
# config.yml
xsd2php:
...
aliases:
'http://www.w3.org/2001/XMLSchema':
anyType: 'MyCustomAnyTypeHandler'
anySimpleType: 'MyCustomAnySimpleTypeHandler'
Now you have to create a custom serialization handler:
use JMS\Serializer\XmlSerializationVisitor;
use JMS\Serializer\XmlDeserializationVisitor;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\VisitorInterface;
use JMS\Serializer\Context;
class MyHandler implements SubscribingHandlerInterface
{
public static function getSubscribingMethods()
{
return array(
array(
'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
'format' => 'xml',
'type' => 'MyCustomAnyTypeHandler',
'method' => 'deserializeAnyType'
),
array(
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'format' => 'xml',
'type' => 'MyCustomAnyTypeHandler',
'method' => 'serializeAnyType'
)
);
}
public function serializeAnyType(XmlSerializationVisitor $visitor, $data, array $type, Context $context)
{
// serialize your object here
}
public function deserializeAnyType(XmlDeserializationVisitor $visitor, $data, array $type)
{
// deserialize your object here
}
}
Naming Strategy
There are two types of naming strategies: short
and long
. The default is short
, this naming strategy can however generate naming conflicts.
The long
naming strategy will suffix elements with Element
and types with Type
.
MyNamespace\User
will becomeMyNamespace\UserElement
MyNamespace\UserType
will becomeMyNamespace\UserTypeType
An XSD for instance with a type named User
, a type named UserType
, a root element named User
and UserElement
, will only work when using the long
naming strategy.
- If you don't have naming conflicts and you want to have short and descriptive class names, use the
short
option. - If you have naming conflicts use the
long
option. - If you want to be safe, use the
long
option.
Note
The code in this project is provided under the MIT license. For professional support contact goetas@gmail.com or visit https://www.goetas.com