i-complex/xsd2php

将 XSD (XML Schema) 定义转换为 PHP 类和 JMS 元数据

0.1.0 2024-04-11 04:08 UTC

README

Build Status Code Coverage Scrutinizer Code Quality

将 XSD 转换为 PHP 类。

使用 goetas-webservices/xsd2php,您可以将任何 XSD/WSDL 定义转换为 PHP 类。

XSD2PHP 还可以生成与 JMS Serializer 兼容的元数据,可用于序列化/反序列化对象实例。

安装

通过 Composer 安装 xsd2php 是一种推荐的方式

  • 将依赖项添加到您的 composer.json 文件中
  "require": {
      ..
      "goetas-webservices/xsd2php-runtime":"^0.2.2",
      ..
  },
  "require-dev": {
      ..
      "goetas-webservices/xsd2php":"^0.3",
      ..
  },

用法

在这个例子中,我们将把 OTA XSD 定义 转换为 PHP 类。

假设您所有的 XSD 文件都在 /home/my/ota 中,首先我们需要一个配置文件(例如 config.yml),它将保存所有命名空间和目录映射信息。

# 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
# configs_jms:  #optional
#   xml_cdata: false # Disables CDATA

以下是每个参数意义的说明

  • xsd2php.namespaces(必需)定义了 XML 命名空间和 PHP 命名空间之间的映射。 (在示例中,http://www.example.org/test/ XML 命名空间映射到 TestNs\MyApp

  • xsd2php.destinations_php(必需)指定保存属于 TestNs\MyApp PHP 命名空间 PHP 类的目录。 (在这个示例中,TestNs\MyApp 类将被保存到 soap/src 目录中。)

  • xsd2php.destinations_jms(必需)指定保存属于 TestNs\MyApp PHP 命名空间 JMS Serializer 元数据文件的目录。 (在这个示例中,TestNs\MyApp 元数据将被保存到 soap/metadata 目录中。)

  • xsd2php.aliases(可选)指定了一些由自定义 JMS serializer 处理器处理的映射。 允许指定不要为某些 XML 类型生成元数据,并直接分配一个 PHP 类。为此,需要为该 PHP 类创建一个自定义 JMS 序列化/反序列化处理器。

  • xsd2php.naming_strategy(可选)指定在将 XML 名称转换为 PHP 类时使用的命名策略。

  • xsd2php.path_generator(可选)指定用于路径生成和文件保存的策略

  • xsd2php.known_locations(可选)用本地文件覆盖远程位置。

  • xsd2php.known_namespace_locations(可选)通过命名空间指定模式位置。 这可以用于读取导入命名空间但未指定 schemaLocation 属性的模式。

  • xsd2php.configs_jms.xml_cdata(可选)指定在序列化时是否应使用 CDATA。

生成 PHP 类和 JMS 元数据信息

vendor/bin/xsd2php convert config.yml /home/my/ota/OTA_Air*.xsd

此命令将为匹配 /home/my/ota/OTA_Air*.xsd 的所有 XSD 文件生成 PHP 类和 JMS 元数据文件,并使用 config.yml 中的配置。

序列化/反序列化

XSD2PHP 还可以为您生成 JMS Serializer 元数据,您可以使用这些元数据来序列化/反序列化生成的 PHP 类实例。

配置文件中的 aliases 参数将指示 XSD2PHP 不要为 {http://www.example.org/test/}MyCustomXSDType 类型生成任何元数据信息或 PHP 类。所有对此类型的引用都将替换为 MyCustomMappedPHPType 名称。

您必须为此类型/别名提供一个 自定义序列化器

以下是一个配置JMS序列化器以处理自定义类型的示例

<?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');

要禁用CDATA,请按如下配置JMS

xsd2php:
  configs_jms:
    xml_cdata: false

验证

<?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:anyTypexsd:anySimpleType

如果您的XSD包含xsd:anyTypexsd:anySimpleType类型,您必须指定一个处理程序。

当您生成JMS元数据时,必须指定一个自定义处理程序

# config.yml

xsd2php:
  ...
  aliases: 
    'http://www.w3.org/2001/XMLSchema':
      anyType: 'MyCustomAnyTypeHandler'
      anySimpleType: 'MyCustomAnySimpleTypeHandler'

现在您必须创建一个自定义序列化处理程序

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
    }
}

命名策略

有两种类型的命名策略:shortlong。默认是short,但这种命名策略可能会生成命名冲突。

long命名策略将在元素后缀Element,在类型后缀Type

  • MyNamespace\User将变为MyNamespace\UserElement
  • MyNamespace\UserType将变为MyNamespace\UserTypeType

例如,一个XSD,其中有一个名为User的类型,一个名为UserType的类型,一个根元素名为UserUserElement,只有在使用long命名策略时才能正常工作。

  • 如果您没有命名冲突并且希望有简短且描述性的类名,请使用short选项。
  • 如果您有命名冲突,请使用long选项。
  • 如果您想确保安全,请使用long选项。

注意

本项目的代码在MIT许可证下提供。如需专业支持,请联系goetas@gmail.com或访问https://www.goetas.com