我正在尝试从 FHIR 项目提供的模式生成 c# 类:http: //hl7.org/implement/standards/fhir/ 我已经下载了模式: http ://hl7.org/documentcenter/public/standards/FHIR /fhir-all-xsd.zip 我已经“解封”了 zip 文件并将 xsd 文件解压缩到一个文件夹中。在尝试使用 xsd.exe 创建 c# 类时,我不断收到表明架构存在问题的错误。除了其他元素之外,没有声明一致地获取xhtml:div 元素。文件fhir-all.xsd似乎列出了顶级对象。我能够让简单的模式tombstone.xsd与 xsd.exe 一起使用,但是更复杂的项目,如valueset.xsd 或 alert.xsd 惨败。我看不出这些文件有什么问题。任何有关如何修复这些模式的帮助将不胜感激。
4 回答
然而,从 XSD 生成 POCO 将提供不太理想的类。由于 FHIR 的序列化避免了使用多态,呈现选择的元素(例如 Observation.value)将在 XSD 中表示为具有相同名称的元素集(valueNumber、valueString、valueCodeableConcept 等)。
同样,很难使用相同的 POCO 进行 json 序列化。
在 FHIR 的 .NET NuGet 包中,您会发现一组为 FHIR 资源生成的类,这些类是我可以制作的最轻量级的。此外,还有 Validation 属性来验证其内容,该包包含用于 json 和 xsd 的序列化器和解析器以及用于调用服务器上的其余操作的 REST 客户端。
如果您需要将解析器和序列化程序与 WebAPI 集成,我已在此处发布:HL7 FHIR serialization to json in asp.net web api
首先,您需要了解 FHIR XSD 文件描述了两个相同的 XML Schema 集:一个“详细”的,它维护标准的逻辑打包(并且它使用大量 <xsd:include>),以及一个“单一的" 一,出于互操作性的原因,它不使用include
指令,即针对特定命名空间的所有内容都放在一个 XSD 文件中。
这是两套,你只需要使用一套。详细集:
...和“每个命名空间的单个文件”之一:
正如我在这篇文章中解释的那样,您应该参考“单人”套装。与那篇文章不同,您不需要其他工具来折叠所有这些 XSD 文件,您将获得“单一”集。
构建遍历第二张图的命令行,从上到下,从左到右,您应该摆脱与未定义内容相关的所有问题。
在这里,您会遇到一些所谓的 xsd.exe 限制,即支持循环组引用。微软说不是(至少在这里和这里);XSD 1.0 规范和XSD 1.1 规范都读到了
没有循环组。也就是说,在一个群的 {particles} 内,没有任何深度的粒子 {term} 是这个群本身。
xsd.exe 使用的上述解释导致了问题。xhtml1-strict.xsd 文件充满了“循环组”依赖项。您将无法 使用 xsd.exe转义这些错误,除非您修复该文件(我们曾经为客户端做过一次)或按照 FHIR 库似乎处理 HTML 标记的相同行修改对任何 xhtml 内容的引用。后一种方法更符合那种不应该为 HTML 标记生成代码绑定的观点,因为它具有混合内容的性质,这使得它在所有代码中都是无用的(至少没有往返可能,也没有正确读取文本节点)我能想到的绑定技术,包括 .NET 的序列化。
鉴于@GrahameGrieve 的第二条评论,我应该明确指出.NET 的内置XSD 处理器正确地验证了XHTML 模式。因此,这不是 .NET XSD 处理器问题,而是 xsd.exe 所依赖的 .NET 其他部分的问题(更具体地说,它是 xsd.exe 进行的外部调用,XmlSchemaImporter.ImportTypeMapping失败惨)
我会责怪规范不够清晰,以避免这种混淆,在我看来,这部分归咎于主流产品行为不端。
到目前为止,我已经能够生成类并反序列化许多提供给所描述的生成的原始类以及 SOAP 服务从原始类生成的类的 Patient*.xml 样本。
编辑 xhtml1-strict.xsd 来解决这个问题并不是那么简单。我使用 xsd.exe 尝试从文件创建类,然后使用错误消息作为起点。经过一些实验,我想出了这个文件。它解决了 div 元素的问题,只要包含的 HTML 保持简单。我正在分享差异报告供其他人使用。数字代表行号。(由于大小限制,我只是分享更改,我试图分享整个文件)。
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"/>-->
到目前为止,我还分享了关于需要手动编辑的笔记,以解决生成的类中的问题。
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
感谢Petru,命令是: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
并且在将循环引用从 xhtml1-strict.xsd 中注释掉之后,确实会创建类
然而,正如 Ewout 指出的那样,这不是一个完整的解决方案,因为模式本身被设计为对 POCO 类不友好。
在患者类中,此元素:
<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>
产量:
/// <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;
}
}
我已经在 FHIR 评论中报告了这些发现,并希望它们能够得到解决。与此同时,我可以继续我的初衷。使用这些定义的 API 的 SOAP 实现。