Question

I am attempting to generate c# classes from schemas provided by the FHIR project: http://hl7.org/implement/standards/fhir/ I have downloaded the schemas: http://hl7.org/documentcenter/public/standards/FHIR/fhir-all-xsd.zip I have "Unblocked" the zip file and unzipped the xsd files into a folder. While attempting to use xsd.exe to create c# classes, I keep getting errors that indicate an issue with the schemas. Consistently getting xhtml:div element is not declared in addition to others. The file fhir-all.xsd seems to list the top level objects. I was able to get the simple schema tombstone.xsd to work with xsd.exe, but a more complex item like valueset.xsd or alert.xsd fails miserably. I can't see what is wrong with these files. Any help on how to fix these schemas will be appreciated.

Was it helpful?

Solution 2

So far I have been able to generate classes and de-serialize many of the patient*.xml samples provided to both raw classes generated as described, and classes generated from the raw classes by a SOAP service.

Editing xhtml1-strict.xsd to fix this issue is not that simple. I used xsd.exe to attempt to create classes from the file, then used the error messages as starting points. After some experimentation, I cam up with this file. It addresses the problem with the div element, as long the HTML contained is kept simple. I am sharing the difference report for others to make use of. The numbers represent line-number. (I am just sharing the changes because of size limitations, I tried to share the whole file).

XSD\xhtml1-strict.xsd(413):      <!--<xs:group ref="inline"/>-->
XSD\xhtml1-strict.xsd(441):      <!--<xs:element ref="pre"/>-->
XSD\xhtml1-strict.xsd(443):      <!--<xs:element ref="blockquote"/>-->
XSD\xhtml1-strict.xsd(462):      <!--<xs:group ref="misc"/>-->
XSD\xhtml1-strict.xsd(519):      <!--<xs:group ref="block"/>-->
XSD\xhtml1-strict.xsd(520):      <!--<xs:group ref="misc"/>-->
XSD\xhtml1-strict.xsd(539):      <!--<xs:group ref="misc"/>-->
XSD\xhtml1-strict.xsd(1349):        <!--<xs:group ref="block"/>-->
XSD\xhtml1-strict.xsd(1351):        <!--<xs:group ref="inline"/>-->
XSD\xhtml1-strict.xsd(1352):        <!--<xs:group ref="misc"/>-->
XSD\xhtml1-strict.xsd(1450):          <!--<xs:group ref="block"/>-->
XSD\xhtml1-strict.xsd(1452):          <!--<xs:group ref="misc"/>-->
XSD\xhtml1-strict.xsd(1718):          <!--<xs:group ref="block"/>-->
XSD\xhtml1-strict.xsd(1720):          <!--<xs:group ref="inline"/>-->
XSD\xhtml1-strict.xsd(1721):          <!--<xs:group ref="misc"/>-->

I am also sharing my notes so far regarding manual edits required, to fix issues in the classes generated.

Generate entities with Xsd2Code add-in from www.codeplex.com\Xsd2Code

Use fhir-atom-single.xsd as the source XSD
Use Parms:
    Serilization.GenerateXMLAttributes = true
    Code.Namespace = Hl7.Fhir.Validation.SchematronOutput
    Collection.CollectionObjectType=Array

!!! Do not open Schema in Designer, or classes will change.

Manual updates:

    public partial class boolean : Element
    ...
        [System.Xml.Serialization.XmlAttributeAttribute("value")]
        public bool Value
        {


    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = false, Namespace = "http://www.w3.org/1999/xhtml")]
    public partial class div : Flow


    Refactor:
    public partial class FeedType
    to
    public partial class feed

OTHER TIPS

Generating POCO's from the XSD's will give less-then-optimal classes however. Since FHIR's serialization avoids the use of polymorhism, elements that present a choice (e.g. Observation.value) will be represented in the XSD as sets of elements with identical names (valueNumber, valueString, valueCodeableConcept etc. etc).

As well, it's pretty hard to use the same POCO's for json serialization.

In the .NET NuGet package for FHIR, you'll find a set of generated classes for the FHIR Resources, which are as light-weight as I could make them. In addition, there are Validation attributes to validate their contents, the package contains serializers and parsers for json and xsd and a REST client to invoke the rest operations on a server.

If you need to integrate the parsers and serializers with WebAPI, I have posted about that here: HL7 FHIR serialisation to json in asp.net web api

First, you need to understand that the FHIR XSD files describe two identical XML Schema sets: a "verbose" one, that maintains the logical packaging of the standard (and it uses a lot of <xsd:include>), and a "single" one, where for interoperability reasons, it does not use include directives i.e. all the content targeting a particular namespace goes in one XSD file.

These are the two sets, you need to use only one. The verbose set:

enter image description here

... and the "single file per namespace" one:

enter image description here

As I've explained in this post, you should refer to the "single one" set. Unlike that post, you don't need another tool to collapse all these XSD files, you are given the "single" set.

Build the command line traversing the second diagram, top to bottom, left to right, and you should get rid of all the problems related to undefined content.

This is where you run into what some call a limitation in xsd.exe, regarding support for circular group references. Microsoft says it is not (here and here at least); both XSD 1.0 spec and XSD 1.1 spec read that

There are no circular groups. That is, within the {particles} of a group there is no particle at any depth whose {term} is the group itself.

The interpretation of the above in what xsd.exe uses, causes the problem. The xhtml1-strict.xsd file is riddled with "circular group" dependencies. You'll not be able to escape those errors using xsd.exe unless you fix that file (we did it for a client once) or modify references to any xhtml content along the same lines the FHIR library seems to deal with HTML markup. The latter approach is more consistent with that view where one should not generate code bindings for HTML markup due to its mixed content nature, which make it useless (at least there's no roundtrip possible, nor correct reading of the text nodes) in all the code binding technologies I could think of, including .NET's serialization.

Given @GrahameGrieve's second comment, I should've pointed out explicitly that .NET's built in XSD processor correctly validates the XHTML schema. So this is not a .NET XSD processor issue, but rather an issue in other parts of the .NET which xsd.exe relies on (to be even more specific, it is an external call xsd.exe makes, XmlSchemaImporter.ImportTypeMapping which fails miserably)

This one I would blame the spec for not being clearer, to avoid this kind of confusion which in my opinion is partly to blame for having a mainstream product misbehaving.

Thanks to Petru, the command is: xsd.exe fhir-atom-single.xsd tombstone.xsd fhir-single.xsd opensearch.xsd opensearchscore.xsd xmldsig-core-schema.xsd xhtml1-strict.xsd xml.xsd /c

and the classes do get created after the circular references are commented out of xhtml1-strict.xsd

However, as Ewout points out this is not a complete fix, because the schemas themselves are designed to be unfriendly to POCO classes.

In the patient class this element:

  <xs:choice minOccurs="0" maxOccurs="1" >
    <xs:annotation>
      <xs:documentation>Indicates if the individual is deceased or not.</xs:documentation>
    </xs:annotation>
    <xs:element name="deceasedBoolean" type="boolean"/>
    <xs:element name="deceasedDateTime" type="dateTime"/>
  </xs:choice>

Yields:

/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("deceasedBoolean", typeof(boolean))]
[System.Xml.Serialization.XmlElementAttribute("deceasedDateTime", typeof(dateTime))]
public Element Item {
    get {
        return this.itemField;
    }
    set {
        this.itemField = value;
    }
}

I have reported these findings on the FHIR comments and hope they will be addressed. In the meantime I can proceed with my original intention. A SOAP implementation of an API using these definitions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top