0 votes

When running xmllint against the generated schema there are several validation errors:

Skipper v3.2.32.1734
Doctrine ORM v2.8.5

Running

xmllint --noout --schema vendor/doctrine/orm/doctrine-mapping.xsd data/orm/Money.Money.dcm.xml

with the generated schema (data/orm/Money.Money.dcm.xml):

<?xml version="1.0"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
  <embeddable name="Money\Money" class-type="embeddable">
    <field name="amount" type="bigint" nullable="false"/>
    <field name="currency" type="currency" nullable="false"/>
  </embeddable>
</doctrine-mapping>

Gives the following errors:

data/orm/Money.Money.dcm.xml:2: element doctrine-mapping: Schemas validity error : Element '{http://doctrine-project.org/schemas/orm/doctrine-mapping}doctrine-mapping', attribute 'xsi': The attribute 'xsi' is not allowed.
data/orm/Money.Money.dcm.xml:2: element doctrine-mapping: Schemas validity error : Element '{http://doctrine-project.org/schemas/orm/doctrine-mapping}doctrine-mapping', attribute 'schemaLocation': The attribute 'schemaLocation' is not allowed.
data/orm/Money.Money.dcm.xml:3: element embeddable: Schemas validity error : Element '{http://doctrine-project.org/schemas/orm/doctrine-mapping}embeddable', attribute 'class-type': The attribute 'class-type' is not allowed.
data/orm/Money.Money.dcm.xml fails to validate
warning: failed to load external entity "2"

The corrected XML validates:

<?xml version="1.0"?>
<doctrine-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                          https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
    <embeddable name="Money\Money">
        <field name="amount" type="bigint" nullable="false"/>
        <field name="currency" type="currency" nullable="false"/>
   </embeddable>
</doctrine-mapping>

The formatting I can deal with, but is there any way to remove/correct the invalid attributes and update to the correct XML header?

in Solved by (730 points)
recategorized by

Hello Ise,

thanks for the info, we will fix that.

Hello Ise,

Do you have any idea why XSD schema located on https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd doesn't work with xmllint (and any other schema validator?)

xmllint --noout --schema doctrine-mapping.xsd  test.xml
The XML document 'doctrine-mapping.XSD is not a schema document.
WXS schema doctrine-mapping.xsd failed to compile

I also tried to find another source for doctrine-mapping.xsd file but without success. I found only some old versions which contains a lot of false positives for valid XML files (for example invalid order of inner elements in entity tag.

Thanks for reply

I probably solved it, but I don't understand that.

When I change the header of xsd schema from this one

<xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema"
targetNamespace="https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
xmlns:orm="https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
elementFormDefault="qualified">

to this one

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:orm="http://doctrine-project.org/schemas/orm/doctrine-mapping"
elementFormDefault="qualified">

xmlling begins to work as expected. So probably some https issue.

We will try to integrate xsd validation to our unit tests, so we can test all of 1000+ doctrine samples against xsd schema to ensure that everything is ok.

I will let you know.

It seems that also https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd XSD document isn't in sync with the latest features of the Doctrine2.

This makes a whole validation almost impossible.

For example, cascade element for associations can contain following values:

  <cascade-persist />
  <cascade-merge />
  <cascade-remove />
  <cascade-refresh />

https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/xml-mapping.html#cascade-element

but XSD schema contains only following rules:

<xs:complexType name="cascade-type">
   <xs:choice minOccurs="0" maxOccurs="unbounded">
     <xs:element name="cascade-all" type="orm:emptyType" minOccurs="0"/>
     <xs:element name="cascade-persist" type="orm:emptyType" minOccurs="0"/>
     <xs:element name="cascade-remove" type="orm:emptyType" minOccurs="0"/>
     <xs:element name="cascade-refresh" type="orm:emptyType" minOccurs="0"/>
   </xs:choice>

som cascade-merge is invalid value by XSD schema but valid by documentation. This unfortunately makes a whole validation almost useless.....

1 Answer

0 votes
Best answer

Hi,

we just released a new beta that contains as many XSD fixes as possible.

https://www.skipper18.com/support/402/downloads-skipper-beta

As I wrote before, unfortunately, there are some areas where XSD isn't in sync with documentation. So in these cases, it will be necessary to report it to the Doctrine team for fix.

Please try it and let me know in case you will find any other inconsistencies. But all our unit tests are now passing (after removing cascade-merge for example).

by Skipper developer (141k points)
selected by

Can you please confirm that this improvement work for you?

Hi Ludek,

Wow very much appreciated with all this work. I was not expecting such a speedy response. Yes I had the same HTTPS issues and I fell back to using the schema defined in the doctrine/orm composer package (vendor/doctrine/orm/doctrine-mapping.xsd) to do the linting. Any areas where the schema is not up to date I'll report to the doctrine team, but I have a feeling its the documentation which is out of date as there are a number of instances where changes have been made and the documentation not updated.

Many many many thanks.

Gary Lockett

You're welcome.

We also clean up several configuration flags/options based on the XSD so it was a win-win ;-).

In case you will find anything we missed, please let me know.

Tried this on one of our major projects and everything passed/worked first time with no mapping changes queued by doctrine migrations so I count that as a success. I have between 40-50 projects that I've used skipper on so I'll run this across everything, see if doctrine reports any mapping changes and let you know.

TLDR: The cascade element is being placed below the join-column element which apparently is a validation error. Placing the cascade element before the join-column element passes successfully.

Just going through these one by one and so far the only thing that's come up is that the following skipper.module.xml:

<?xml version="1.0"?>
<skipper version="3.2.34.1746" mvc="Without MVC" orm="Doctrine2">
  <module name="\Stratum\Gallery" local-name="Stratum\Gallery" namespace="\Stratum\Gallery\Entity" local-namespace="Stratum\Gallery\Entity" export-format="Doctrine2Xml" export-path="data/orm" uuid="a47f1d1a-8828-4679-b412-f84679e6accf">
    <entity name="\Stratum\Gallery\Entity\AbstractMedia" local-name="AbstractMedia" namespace="\Stratum\Gallery\Entity" uuid="7cb2e31f-375c-42c0-a0c0-1f37c9c3f94c">
      <field name="type" type="string" required="true" uuid="1997d89d-8737-46e8-8f65-f370bcc26212"/>
      <field name="content_identity" type="guid" required="true" unique="true" uuid="c4320b50-9f42-48c1-92f5-e35a20e7a26a"/>
      <field name="mimeType" type="string" required="true" uuid="86850bdf-5811-4bb9-b423-593aeb2168da"/>
      <field name="path" type="string" required="true" uuid="d99a4f88-3cdb-4acf-8e07-401c537ea1df"/>
      <field name="filename" type="string" required="true" uuid="96e9e3cb-b059-44ff-9b5b-a5e393e0b7e5"/>
      <index name="UniqueFile" unique="true" uuid="170702bf-3894-476e-9037-fe970cf33cfc">
        <index-field name="path" uuid="6990a44b-2581-494d-aa87-ba8772118b0e"/>
        <index-field name="type" uuid="f46e6368-191d-42f5-86f9-82fff296d3df"/>
        <index-field name="filename" uuid="b9f83bc9-442d-4b5c-9206-4735a47ee422"/>
      </index>
      <inheritance-parent discriminator-field="type" type="JOINED" uuid="add021fe-20ac-4244-b135-c48723cfef60"/>
      <inheritance-child derived-from="\Stratum\Doctrine\Entity\AbstractAuditableEntity" uuid="03c520f3-7770-4b6d-b610-d63adaf3c8b0"/>
      <orm-attributes>
        <attribute name="options">
          <attribute name="charset">utf8mb4</attribute>
          <attribute name="collate">utf8mb4_unicode_ci</attribute>
        </attribute>
        <attribute name="table">gallery_media</attribute>
      </orm-attributes>
    </entity>
    <association from="\Stratum\Gallery\Entity\AbstractMedia" to="\Stratum\Gallery\Entity\MediaContent" inverse-alias="content" many-owner="false" many-inverse="false" parent-required="true" uuid="1d6656ef-cc24-482c-9232-3a613465ee9d">
      <association-field from="content_identity" to="identity" uuid="b6bac7b4-de05-4097-b499-eab4b52299ee"/>
      <orm-attributes>
        <attribute name="on-delete">CASCADE</attribute>
        <attribute name="side-owning">
          <attribute name="cascade">
            <attribute name="cascade-all">true</attribute>
          </attribute>
          <attribute name="fetch">EXTRA_LAZY</attribute>
        </attribute>
      </orm-attributes>
    </association>
    <entity name="\Stratum\Gallery\Entity\Image" local-name="Image" namespace="\Stratum\Gallery\Entity" uuid="9ac048cd-1d6f-4ae9-a698-0eb6b98efad5">
      <field name="width" type="integer" required="true" uuid="23618b11-e8ca-43fd-8f2f-4ab83714de0c"/>
      <field name="height" type="integer" required="true" uuid="b1eacb2b-26d2-48ef-9afa-0c2bada9e05d"/>
      <inheritance-child derived-from="\Stratum\Gallery\Entity\AbstractMedia" discriminator-value="image" uuid="2f39e4a1-c4f1-4fec-af4b-d41f048e2476"/>
      <orm-attributes>
        <attribute name="options">
          <attribute name="charset">utf8mb4</attribute>
          <attribute name="collate">utf8mb4_unicode_ci</attribute>
        </attribute>
        <attribute name="table">gallery_images</attribute>
      </orm-attributes>
    </entity>
    <entity name="\Stratum\Gallery\Entity\Video" local-name="Video" namespace="\Stratum\Gallery\Entity" uuid="8113d535-2fd5-46c4-939c-df82ac0586cd">
      <field name="autoplay" type="boolean" required="true" uuid="d9562fac-0b6b-4655-a209-78b352aeae1d"/>
      <field name="loop" type="boolean" required="true" uuid="b884c74f-e87e-45a4-bd69-fe861804edbe"/>
      <inheritance-child derived-from="\Stratum\Gallery\Entity\AbstractMedia" discriminator-value="video" uuid="5c418e06-00aa-49f5-9442-65dd97afa971"/>
      <orm-attributes>
        <attribute name="options">
          <attribute name="charset">utf8mb4</attribute>
          <attribute name="collate">utf8mb4_unicode_ci</attribute>
        </attribute>
        <attribute name="table">gallery_videos</attribute>
      </orm-attributes>
    </entity>
    <entity name="\Stratum\Gallery\Entity\File" local-name="File" namespace="\Stratum\Gallery\Entity" uuid="8f295f0e-d7d3-40fe-8329-ed3d5fa38bcb">
      <inheritance-child derived-from="\Stratum\Gallery\Entity\AbstractMedia" discriminator-value="file" uuid="2f083f91-8aca-40e2-b8fe-adffba9609a4"/>
      <orm-attributes>
        <attribute name="table">gallery_files</attribute>
      </orm-attributes>
    </entity>
    <entity name="\Stratum\Gallery\Entity\MediaContent" local-name="MediaContent" namespace="\Stratum\Gallery\Entity" uuid="54d1ee78-67b7-4dfe-b867-1468ee72a8ca">
      <field name="data" type="blob" required="true" uuid="cf56f305-772b-433b-be36-bffd8b083eb1"/>
      <inheritance-child derived-from="\Stratum\Doctrine\Entity\AbstractGuidEntity" uuid="b5f4d2bb-e45c-44ab-9c01-6c04766c413d"/>
      <orm-attributes>
        <attribute name="table">gallery_media_content</attribute>
      </orm-attributes>
    </entity>
  </module>
  <visual-data>
    <entity uuid="54d1ee78-67b7-4dfe-b867-1468ee72a8ca" bg-color="#FFFFFF" hdr-color="#D2D2D2" position-x="55" position-y="102" size-x="0" size-x2="82" size-y="0" size-y2="46"/>
    <entity uuid="7cb2e31f-375c-42c0-a0c0-1f37c9c3f94c" bg-color="#FFFFFF" hdr-color="#D2D2D2" position-x="176" position-y="67" size-x="0" size-x2="158" size-y="0" size-y2="144"/>
    <entity uuid="8113d535-2fd5-46c4-939c-df82ac0586cd" bg-color="#FFFFFF" hdr-color="#D2D2D2" position-x="-80" position-y="96" size-x="0" size-x2="118" size-y="0" size-y2="116"/>
    <entity uuid="8f295f0e-d7d3-40fe-8329-ed3d5fa38bcb" bg-color="#FFFFFF" hdr-color="#D2D2D2" position-x="177" position-y="205" size-x="0" size-x2="101" size-y="0" size-y2="73"/>
    <entity uuid="9ac048cd-1d6f-4ae9-a698-0eb6b98efad5" bg-color="#FFFFFF" hdr-color="#D2D2D2" position-x="327" position-y="67" size-x="0" size-x2="101" size-y="0" size-y2="102"/>
    <inheritance-child uuid="03c520f3-7770-4b6d-b610-d63adaf3c8b0" caption1-position-x="0" caption1-position-y="0" center-position-x="0" center-position-y="0" color="#969696" split="1"/>
    <inheritance-child uuid="2f083f91-8aca-40e2-b8fe-adffba9609a4" center-position-x="0" center-position-y="0" color="#969696"/>
    <inheritance-child uuid="2f39e4a1-c4f1-4fec-af4b-d41f048e2476" caption1-position-x="0" caption1-position-y="0" center-position-x="0" center-position-y="0" color="#969696"/>
    <inheritance-child uuid="5c418e06-00aa-49f5-9442-65dd97afa971" caption1-position-x="0" caption1-position-y="0" center-position-x="0" center-position-y="0" color="#969696"/>
    <inheritance-child uuid="b5f4d2bb-e45c-44ab-9c01-6c04766c413d" caption1-position-x="0" caption1-position-y="0" center-position-x="0" center-position-y="0" color="#969696" split="1"/>
    <module uuid="a47f1d1a-8828-4679-b412-f84679e6accf" bg-color="#E7F5FD" size-x="89" size-x2="461" size-y="-24" size-y2="453"/>
  </visual-data>
</skipper>

Generates the following mapping for "Stratum.Gallery.Entity.AbstractMedia.dcm.xml":

<?xml version="1.0"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
  <entity name="Stratum\Gallery\Entity\AbstractMedia" inheritance-type="JOINED" table="gallery_media">
    <field name="mimeType" type="string" nullable="false"/>
    <field name="path" type="string" nullable="false"/>
    <field name="filename" type="string" nullable="false"/>
    <unique-constraints>
      <unique-constraint name="UniqueFile" columns="path,type,filename"/>
    </unique-constraints>
    <one-to-one field="content" target-entity="Stratum\Gallery\Entity\MediaContent" fetch="EXTRA_LAZY">
      <join-columns>
        <join-column name="content_identity" referenced-column-name="identity" nullable="false" unique="true" on-delete="CASCADE"/>
      </join-columns>
      <cascade>
        <cascade-all/>
      </cascade>
    </one-to-one>
    <discriminator-column name="type" type="string"/>
    <discriminator-map>
      <discriminator-mapping class="Stratum\Gallery\Entity\Image" value="image"/>
      <discriminator-mapping class="Stratum\Gallery\Entity\Video" value="video"/>
      <discriminator-mapping class="Stratum\Gallery\Entity\File" value="file"/>
    </discriminator-map>
    <options>
      <option name="charset">utf8mb4</option>
      <option name="collate">utf8mb4_unicode_ci</option>
    </options>
  </entity>
</doctrine-mapping>

Which gives the following error:

data/orm/Stratum.Gallery.Entity.Video.dcm.xml validates
data/orm/Stratum.Gallery.Entity.File.dcm.xml validates
data/orm/Stratum.Gallery.Entity.MediaContent.dcm.xml validates
data/orm/Stratum.Gallery.Entity.Image.dcm.xml validates
data/orm/Stratum.Gallery.Entity.AbstractMedia.dcm.xml:14: element
cascade: Schemas validity error : Element
'{http://doctrine-project.org/schemas/orm/doctrine-mappi ng}cascade':
This element is not expected. Expected is (##other{http://doctrine-project.org/schemas/orm/doctrine-mapping}* ).
data/orm/Stratum.Gallery.Entity.AbstractMedia.dcm.xml fails to
validate.

I took at look at the schema and I couldn't see any issues and its not exactly reporting that its completely wrong. So I tried sorting the elements alphabetically (specifically placing the element inside the before the element) and this appears to resolve this issue.

(i.e. this works)

<one-to-one field="content" target-entity="Stratum\Gallery\Entity\MediaContent" fetch="EXTRA_LAZY">
  <cascade>
    <cascade-all/>
  </cascade>
  <join-columns>
    <join-column name="content_identity" referenced-column-name="identity" nullable="false" unique="true" on-delete="CASCADE"/>
  </join-columns>
</one-to-one>

This is one of the issues in the XSD schema shipped by Doctrine in comparison to the official XSD schema.

Try to download official schema from https and replace all https to HTTP:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:orm="http://doctrine-project.org/schemas/orm/doctrine-mapping"
elementFormDefault="qualified">

after that, please try the validation again. I'm testing your sample and it's valid:

xmllint --noout --schema doctrine-mapping.xsd  SampleEntity.orm.xml
SampleEntity.orm.xml validates

Same as above but with join-table + cascade vs cascade + join-table:

Generated:

<many-to-many field="users" target-entity="Stratum\User\Entity\User">
  <join-table name="rbac_role_users">
    <join-columns>
      <join-column name="role_identity" referenced-column-name="identity" nullable="false"/>
    </join-columns>
    <inverse-join-columns>
      <join-column name="user_identity" referenced-column-name="identity" nullable="false" on-delete="CASCADE"/>
    </inverse-join-columns>
  </join-table>
  <cascade>
    <cascade-all/>
  </cascade>
</many-to-many>

Correct:

<many-to-many field="users" target-entity="Stratum\User\Entity\User">
  <cascade>
    <cascade-all/>
  </cascade>
  <join-table name="rbac_role_users">
    <join-columns>
      <join-column name="role_identity" referenced-column-name="identity" nullable="false"/>
    </join-columns>
    <inverse-join-columns>
      <join-column name="user_identity" referenced-column-name="identity" nullable="false" on-delete="CASCADE"/>
    </inverse-join-columns>
  </join-table>
</many-to-many>

Unfortunately the same as my previous reply. This is the bug in the XSD schema supplied by Doctrine.

Schema available on the official https address doesn't define the order of elements.

Thanks I'll report this to doctrine/orm and fix them manually for now.

There was another issue in a client application where I can't share the XML, but I'm happy to accept this as my issue.

A discriminator-mapping element is being generated for an abstract entity which uses class-table-inheritance. With the value for this base class empty, the fully qualified class name is being used which throws an error.

With that, I've tested everything we have against the latest beta, and it all looks good to me! Thanks again for the fast turn around.

Thanks I'll report this to doctrine/orm and fix them manually for now.

You're welcome. I believe there is no real reason to force explicit XML elements order, so I think XSD file distributed with Doctrine is outdated and XSD file available on the web is latest.

A discriminator-mapping element is being generated for an abstract entity which uses class-table-inheritance. With the value for this base class empty, the fully qualified class name is being used which throws an error.

Would be possible to create some minimal test case and send this to me? Or maybe create copy of your client project, erase all other entities and rename remaining so you can share it?

You're welcome. I believe there is no real reason to force explicit XML elements order, so I think XSD file distributed with Doctrine is outdated and XSD file available on the web is latest.

It appears to be the reverse and that the one on the web is out of date. I think you are correct in using it though as it is unversioned so I'm not sure what else you could do without forcing a Doctrine ORM version on your customers. Here is the open issue I have with them:
https://github.com/doctrine/doctrine-website/issues/405.

Would be possible to create some minimal test case and send this to me? Or maybe create copy of your client project, erase all other entities and rename remaining so you can share it?

I'll see if I can create a minimal reproducible test case and get it to you.

Thanks for the update.

Unfortunately, this means that there are few more issues. Order of elements is forced on several other places and also there was some missing definition.

For now, we would wait until they sync the web version and bundled version. We need to know what is the correct final state and after that, we will continue to work on it. Please let me know when they merge it.

Thanks