views:

411

answers:

2

I have an XML schema that uses enumerations, but when I look at the generated XML object in Delphi, the enumeration restriction has been dropped. Is there any way to get Delphi to generate the enum and build it into the object?

XSD Snippet:

<xs:simpleType name="enumType" final="restriction">
    <xs:restriction base="xs:NMTOKEN">
        <xs:enumeration value="Each"/>
        <xs:enumeration value="Units"/>
        <xs:enumeration value="Area"/>
        <xs:enumeration value="Payroll"/>
        <xs:enumeration value="Sales"/>
        <xs:enumeration value="TotalCost"/>
        <xs:enumeration value="Other"/>
    </xs:restriction>
</xs:simpleType>

What I would expect to see in Delphi is a field that accepts a enum that is then converted to it's corresponing string when the XML is generated, but that field is just an ordinary string.

+2  A: 

What you can do is create your own enumerated type with the same string constants as names and use the unit TypInfo with the function GetEnumValue and GetEnumString. This allows you to prefix the names with a few lowercase letters like in other Delphi code:

Value :=  TMyEnum( GetEnumValue( typeinfo( TMyEnum ), Prefix + AString )  )
Ritsaert Hornstra
Could you explain this example a little more; I have gone ahead and implemented the enumerations, but I'm using string arrays that match the enums I.E: `//Return string Result := enumType_strings[Integer(enumType_Each)];` `//Return enum for ... if aString = enumType_strings[index] then Result := enumType_enums(index); ...` Thanks though, you confirmed my worst fears ;-)
nomad311
If you have an enumeration like TMyEnum = ( meFirst, meSecond, meThird ), you can get the ordinal (numeric) value using EnumValue := TMyEnum( GetEnumValue( typeinfo( TMyEnum ), 'meFirst' ) ); // result will be meFirst. The other way around: Result := Copy( GetEnumName( typeinfo( TMyEnum ), Ord( meSecond ) ), 3, MaxInt ) will yield the string 'Second'. One note: if GetEnumValue will return -1 if the value is not found so you might add an additional test on the result instead of casting it directly to your enumeration type.Good Luck!
Ritsaert Hornstra
That's pretty cool, thanks
nomad311
A: 

It is not possible for the XML data binding wizard to do what you want.

The reason is that enumerations in an XSD are not compatible with delphi identifiers because they:

  1. can contain characters incompatible with a Delphi identifier
  2. are case sensitive

Basically XSD enumerations are just strings with a constrained of values.

See the enumeration specs and an example.

Both are clearly incompatible with Delphi enumeration types.

Edit: 20100125 - Delphi attributes

Here is an interesting question on how far you could go with the new attribute and RTTI support in Delphi 2010.

--jeroen

Jeroen Pluimers
Those sound like excuses to me (not you, whom ever decided not to support XML enums in Delphi, of course). There are any number of solutions to the problem and at some point the actual enums would have to be stored in string constants, there's no reason that there would have to be an enumType.Each option ...its enumType_enums_Each for me. Thanks for the conformation though.
nomad311
With the current language features (attributes, constants), it might be possible to work around this. But remember that Delphi is not alone in these kinds of limitations. Generating wrappers from XSD schema's is the field of specialized tools, even in the Java or .NET world. See the answers here for some tools that work in the .NET world: http://stackoverflow.com/questions/305796/generate-class-for-schema-with-abstract-complex-type
Jeroen Pluimers
Thanks for that, added it to deliciious ...something tells me I'll bee looking for that later
nomad311
And there is much more that won't work. Basically, XSD allows for data structures that are very hard - if not impossible - to map to most programming languages. For instance, in XSD you can derive from an existing type in two ways: extending it and limiting it. Object Oriented languages only allow you extend when deriving.
Jeroen Pluimers