schmittjoh / serializer

Library for (de-)serializing data of any complexity (supports JSON, and XML)
http://jmsyst.com/libs/serializer
MIT License
2.32k stars 588 forks source link

Include attributes on XML serialization #803

Open iamsophiesk opened 7 years ago

iamsophiesk commented 7 years ago

Hiya

I'm trying to build some XML that looks something like this:

<root type="object">
  <Lastname>Test</Lastname>
  <Firstname>Test</Firstname>
  <DateOfBirth type="null" />
</root>

Where the date of birth is a string or null. When I add $contact->setSerializeNull(TRUE); I get something like:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="object">
  <Lastname>Test</Lastname>
  <Firstname>Test</Firstname>
  <DateOfBirth xsi:nil="true"/>
</root>

The XML namespacing is undesirable; the CRM system I'm posting this data to cannot interpret this. I am also unable to change the xsi:nil="true" attribute in the DateOfBirth.

I have set up a DoB class thus:

/**
 * Date field class for use in Records.
 *
 * @XmlRoot("DateOfBirth")
 * @XmlDiscriminator(attribute=true)
 */
class RecordDate {

  /**
   * The type of this value.
   *
   * @XmlAttribute
   */
  private $type = 'null';

  /**
   * The value of this date field.
   *
   * @var string
   *
   * @XmlValue
   * @XmlElement(cdata=false)
   */
  private $date;

  /**
   * Constructor method.
   *
   * @param string $date
   *   The date, pre-converted to an XML string.
   */
  public function __construct($date) {
    $this->date = $date;
  }

}

But this only works for dates where there is a value, eg:

  <CreatedDate type="null">/Date(1501672104000)/</CreatedDate>

Is there a way to force the type="null" attribute? Is there a way to remove the XML namespacing from all elements in the record?

Or should I just revert to SimpleXMLElement again? Totally not what I want to do, but ...

Thanks!

goetas commented 7 years ago

type="null" means that your type is a "string" with value string(4) "null", not NULL

goetas commented 7 years ago

If you need to represent NULL as attribute, it is not an easy thing. I suggest you to use an element... is a controversial topic https://stackoverflow.com/questions/774192/what-is-the-correct-way-to-represent-null-xml-elements

iamsophiesk commented 7 years ago

Thanks for the speedy response. This is all based on a separate system that expects the data in this format, and the client doesn't want to change it (until after we launch the product in ~3-6 months).

When you say "your type is a 'string' with value ...", I have in code:

  /**
   * The type of this value.
   *
   * @XmlAttribute
   */
  private $type = 'null';

So would you expect it to have @Type("string") in the annotation? Hm - not sure what I should change if anything?

goetas commented 7 years ago

@Type("string") should work

iamsophiesk commented 7 years ago

Hmm, nope, I ended up with this:

  <DateOfBirth xsi:nil="true"/>

  <CreatedDate>
    <type>null</type>
    <date>/Date(1501683112000)/</date>
  </CreatedDate>

Code:

  /**
   * The type of this value.
   *
   * @XmlAttribute
   * @XmlElement(cdata=false)
   * @Type("string")
   */
  private $type = 'null';

  /**
   * The value of this date field.
   *
   * @var string
   *
   * @XmlValue
   * @XmlElement(cdata=false)
   */
  private $date;

I think I might just wait for the client to come back to me - it seems like I'm trying to ask the serializer to do something that it just doesn't want to do!