Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sequence order not maintained when choice is between B or A+B #285

Open
kimjamia opened this issue Sep 22, 2021 · 3 comments
Open

Sequence order not maintained when choice is between B or A+B #285

kimjamia opened this issue Sep 22, 2021 · 3 comments

Comments

@kimjamia
Copy link

kimjamia commented Sep 22, 2021

Problem

Given a schema where there's a choice between entering B or a sequence of A+B, the order of the sequence is not maintained in the generated xml even with --order. The --order appends the Order attributes in the wrong order.

How to reproduce

Schema example:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:complexType name="subClass">
    <xsd:sequence>
      <xsd:element name="oneField" type="xsd:string"/>
      <xsd:element name="otherField" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:element name="someClass">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="someElement" type="xsd:string"/>
        <xsd:choice>
          <xsd:element name="secondary" type="xsd:string"/>
          <xsd:sequence>
            <xsd:element name="primary" type="subClass" />
            <xsd:element name="secondary" type="xsd:string" minOccurs="0"/>
          </xsd:sequence>
        </xsd:choice>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Example C# code:

var obj = new SomeClass
{
    SomeElement = "Anything here",
    Primary = new SubClass
    {
        OneField = "some data",
        OtherField = "more data"
    },
    Secondary = "This should appear after primary"
};

var serializer = new XmlSerializer(typeof(SomeClass));
using (var sw = new StringWriter())
using (var xw = XmlWriter.Create(sw))
{
    serializer.Serialize(xw, obj);
    Console.WriteLine(sw.ToString());
}

Resulting xml:

<?xml version="1.0" encoding="utf-16"?>
<someClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <someElement>Anything here</someElement>
  <secondary>This should appear after primary</secondary>
  <primary>
    <oneField>some data</oneField>
    <otherField>more data</otherField>
  </primary>
</someClass>

Expected result

Because I have entered both fields Primary and Secondary, I have effectively picked the second option of the choice which is a sequence and its order should be maintained. I would thus expect the resulting xml to be:

<?xml version="1.0" encoding="utf-16"?>
<someClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <someElement>Anything here</someElement>
  <primary>
    <oneField>some data</oneField>
    <otherField>more data</otherField>
  </primary>
  <secondary>This should appear after primary</secondary>
</someClass>
@mganss
Copy link
Owner

mganss commented Sep 23, 2021

This is due to the way XmlSchemaClassGenerator handles choice elements. It might seem as if the order is wrong, but the Secondary property isn't the second element of the second choice option, it's the first choice option. The second element of the second choice option is dropped because the Secondary property already exists.

The situation would be different if there weren't two elements both named secondary.

I don't see a way out of this while keeping the current way of dealing with choice elements.

Perhaps, if it's feasible within your project, it might be an option to modify the schema so that XmlSchemaClassGenerator generates code that allows for XML that is compatible with the original schema. AFAICT, this should be equivalent:

<xsd:element name="someClass">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="someElement" type="xsd:string"/>
      <xsd:element name="primary" type="subClass" minOccurs="0" />
      <xsd:element name="secondary" type="xsd:string" minOccurs="0"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

@kimjamia
Copy link
Author

What if XmlSchemaClassGenerator added Order-attributes to sequences always? Would that help in this kind of case? How does xscgen maintain the order of sequences usually? I don't think I saw it putting anything sorting-related in the classes.

I ended up adding the Order-attributes to the generated classes. It's not very optimal because the classes can't be regenerated so easily now but I'm not sure which one is least bad, modify a given schema or modify generated code.

@mganss
Copy link
Owner

mganss commented Sep 23, 2021

It's not an order-related issue. The order is already correct, it's just that the second Secondary property is dropped.

The default order of elements in a sequence is simply the enumeration order of XmlSchemaElement objects (which in turn is the order in which the elements occur in the schema I believe).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants