xsd2php
xsd2php copied to clipboard
simpleType union not converted correctly
I'm trying to use xsd2php for OTA 2003/05 / 2014A-1.0. In addition to #71, there's also a problem with the following definition in OTA_SimpleTypes.xsd
<xs:simpleType name="DateOrTimeOrDateTimeType">
<xs:annotation>
<xs:documentation xml:lang="en">A construct to validate either a date or a time or a dateTime value.</xs:documentation>
</xs:annotation>
<xs:union memberTypes="xs:date xs:dateTime xs:time"/>
</xs:simpleType>
The following valid xml causes an error
<TimeSpan Start="2018-11-12T12:00:00" End="2018-11-13T12:00:00"></TimeSpan>
RuntimeException: Invalid date "2018-11-12T12:00:00", expected valid XML Schema date string.
This is the generated DateTimeSpanType.yml
Hsp\latest\DateTimeSpanType:
properties:
start:
expose: true
access_type: public_method
serialized_name: Start
accessor:
getter: getStart
setter: setStart
xml_attribute: true
type: GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Date
…
Looks as if the yml doesn't contain the other valid types. I guess this is not possible?
Does anyone know a workaround? This is real life XML. I cannot influence the XML and when I tried to modify the xsd to use xs:dateTime
only, it choked on another real life XML that has no time part. I need to handle both cases.
is XmlSchemaDateHandler
registered as in https://github.com/goetas-webservices/xsd2php#serialize--unserialize ?
Yes:
…
use GoetasWebservices\Xsd\XsdToPhpRuntime\Jms\Handler\BaseTypesHandler;
use GoetasWebservices\Xsd\XsdToPhpRuntime\Jms\Handler\XmlSchemaDateHandler;
class Serializer
{
/**
* @var JMSSerializer
*/
private $serializer;
public function build($version = 'latest'): Serializer
{
$serializerBuilder = SerializerBuilder::create();
$serializerBuilder->addMetadataDir(
dirname(__FILE__) . "/../generated/${version}/meta",
"Hsp\\${version}"
);
$serializerBuilder->configureHandlers(function (HandlerRegistryInterface $handler) use ($serializerBuilder) {
$serializerBuilder->addDefaultHandlers();
$handler->registerSubscribingHandler(new BaseTypesHandler()); // XMLSchema List handling
$handler->registerSubscribingHandler(new XmlSchemaDateHandler()); // XMLSchema date handling
});
$this->serializer = $serializerBuilder->build();
return $this;
}
public function serialize($model): string
{
return $this->serializer->serialize($model, 'xml');
}
public function deserialize($xmlString, $className)
{
return $this->serializer->deserialize($xmlString, $className, 'xml');
}
}
~the bug looks related to https://github.com/goetas-webservices/xsd2php-runtime/blob/18a9e25e89b719fa5417dcbd6515604723df957d/src/Jms/Handler/XmlSchemaDateHandler.php#L92~
The union type should be detected as GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime
instead of GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Date
.
To solve it you can add a type alias (see alias
in the config file)
Thanks. How am I supposed to configure that? Tried
xsd2php:
…
aliases:
'http://www.opentravel.org/OTA/2003/05/common':
DateOrDateTimeType: 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime'
But that doesn't work. It still resolves to
type: GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Date
Ok. Found the correct alias configuration:
aliases:
'http://www.opentravel.org/OTA/2003/05':
DateOrTimeOrDateTimeType: 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime'
But now, it chokes when I try to set the date in another test:
$statusApplicationControl1 = new StatusApplicationControlType();
$statusApplicationControl1->setStart(Carbon::parse('2018-11-06')->toDate());
Notice that Carbon::toDate
returns a DateTime
. This part of the test worked before I configured the alias.
TypeError: Argument 1 passed to Hsp\latest\StatusApplicationControlType::setStart() must be an instance of GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime, instance of DateTime given, called in […]/tests/SerializerTest.php on line 214
I would use GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime
instead of DateTime if I needed to, but I'm not sure how to do that, because I can't find that type at all.
Can you tell me, how to convert a DateTime
to GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime
?
This is the generated code for StatusApplicationControlType.php:
/**
* Sets a new start
*
* The starting value of the time span.
*
* @param \GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime $start
* @return self
*/
public function setStart(\GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime $start)
{
$this->start = $start;
return $this;
}
So I tested the following:
I removed the alias config that was meant to solve the first problem but caused the wrong type hint in the generated StatusApplicationControlType and other files.
# aliases:
# 'http://www.opentravel.org/OTA/2003/05':
# DateOrTimeOrDateTimeType: 'GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime'
Then I manually changed the generated DateTimeSpanType.yml:
Hsp\latest\DateTimeSpanType:
properties:
start:
expose: true
access_type: public_method
serialized_name: Start
accessor:
getter: getStart
setter: setStart
xml_attribute: true
# from type: GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Date
# to
type: GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime
# same with property "end"
Everything works as expected. But after each conversion, you need to manually adjust the generated yml.
Is there a way to avoid this manual correction? Can I generate the yml with GoetasWebservices\Xsd\XsdToPhp\XMLSchema\DateTime
and keep the \DateTime
typehint in the generated php classes (which finally works as expected)?
/**
* Sets a new start
*
* The starting value of the time span.
*
* @param \DateTime $start
* @return self
*/
public function setStart(\DateTime $start)
{
$this->start = $start;
return $this;
}
having a similar problem, without specifying an alias, typehints generated are \Datetime
, when I add an alias, the typehints are GoetasWebservices\Xsd\XsdToPhp\XMLSchema\Date
, but this class does not seem to exist, at least I could not find it in this package nor the runtime one. What is the correct way of handling date types? are there any docs about this?
@cebe Don't forget to register these custom types.... ie. BaseTypes/XmlSchemaDate
$serializerBuilder->configureHandlers(
static 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());
}
);
Those files come from the namespace GoetasWebservices\Xsd\XsdToPhpRuntime\Jms\Handler;
I think I got it now, thanks for the hint!