【问题标题】:Generating C# classes from FHIR schemas从 FHIR 模式生成 C# 类
【发布时间】:2014-02-18 18:35:18
【问题描述】:

我正在尝试从 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 这样更复杂的项目却惨遭失败。我看不出这些文件有什么问题。任何有关如何修复这些模式的帮助将不胜感激。

【问题讨论】:

  • 您是否在 xsd.exe 命令中包含 .xsd 文件链?
  • 不确定这意味着什么。大多数 xsd 文件似乎都包含引用集合中文件的元素,尤其是 xsd.exe 所说的缺少的元素。
  • 我遇到了类似的问题,不得不告诉 xsd.exe 在 xsds 中引用的所有文件名,只是把它扔在那里,这可能不是你的问题。
  • 您引用的架构集存在更大的问题...为了帮助我理解我应该提供的答案,您是专业用户,还是只是想学习/理解 XSD一般,特别是HL7?
  • 我是一名 .Net 开发人员,我的目的是从这些模式创建 c# 类。我想要简单的支持 POCO 或 LINQ 的数据集,所以我对 FIHR .Net 下载不感兴趣。

标签: c# xsd hl7-fhir


【解决方案1】:

然而,从 XSD 生成 POCO 将提供不太理想的类。由于 FHIR 的序列化避免使用多态,呈现选择的元素(例如 Observation.value)将在 XSD 中表示为具有相同名称的元素集(valueNumber、valueString、valueCodeableConcept 等)。

同样,使用相同的 POCO 进行 json 序列化非常困难。

在 FHIR 的 .NET NuGet 包中,您会找到一组为 FHIR 资源生成的类,这些类是我可以制作的最轻量级的。此外,还有 Validation 属性来验证其内容,该包包含用于 json 和 xsd 的序列化器和解析器以及用于调用服务器上的其余操作的 REST 客户端。

如果您需要将解析器和序列化器与 WebAPI 集成,我已在此处发布了相关信息:HL7 FHIR serialisation to json in asp.net web api

【讨论】:

  • 不错的尝试 :)... 对于侧边栏,我会问为什么 I am not interested in the FIHR .Net download. 评论开头...
  • 在我看来,Fhir 模式存在可以轻松纠正的问题: 1-删除对 xhtml1-strict.xsd 的依赖 - 此模式具有阻止创建类的循环引用。 2-删除模式中选择元素的使用。这些导致类型定义为可以是事物列表的对象。到目前为止,我在规范中看到的真正问题是“文档”将告知开发人员有关结构的想法。文档总是缺失、不完整、过时、错误。像这样的系统中唯一可靠的文档是模式。
  • 您好 jlo,请注意,在 FHIR 规范中,模式实际上是从与文档相同的源生成的,因此模式也是派生的,而不是源。模式不是手动维护的!发布工具从设计源生成网站,生成模式,然后验证示例。 .net 和 java 的源代码也生成了,所以总是最新的!
【解决方案2】:

到目前为止,我已经能够生成类并反序列化许多提供给如前所述生成的原始类和 SOAP 服务从原始类生成的类的患者*.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

【讨论】:

    【解决方案3】:

    首先,您需要了解 FHIR XSD 文件描述了两个相同的 XML Schema 集:一个“详细”的,它维护标准的逻辑打包(并且它使用了很多 ),以及一个“单一”的,出于互操作性的原因,它不使用include 指令,即针对特定命名空间的所有内容都放在一个 XSD 文件中。

    这是两套,你只需要使用一套。详细集:

    ...和“每个命名空间的单个文件”之一:

    正如我已经解释过的in this post,您应该参考“单一”集。与那篇文章不同,您不需要其他工具来折叠所有这些 XSD 文件,您将获得“单一”集。

    构建遍历第二张图的命令行,从上到下,从左到右,你应该摆脱所有与未定义内容相关的问题。

    这是您在 xsd.exe 中遇到一些关于支持循环组引用的限制的地方。微软说不是(至少herehere); XSD 1.0 specXSD 1.1 spec 都读到了

    没有循环组。也就是说,在一个的{粒子}内 群 在任何深度都没有粒子 {term} 是群 自己。

    xsd.exe 使用的上述解释导致了问题。 xhtml1-strict.xsd 文件充满了“循环组”依赖项。 使用 xsd.exe 除非您修复该文件(我们曾经为客户做过一次)或按照 FHIR 库看起来的相同行修改对任何 xhtml 内容的引用,否则您将无法逃避这些错误处理 HTML 标记。后一种方法更符合那种不应该为 HTML 标记生成代码绑定的观点,因为它具有混合内容的性质,这使得它在所有代码中都是无用的(至少没有往返可能,也没有正确读取文本节点)我能想到的绑定技术,包括 .NET 的序列化。

    鉴于@GrahameGrieve 的第二条评论,我应该明确指出.NET 的内置XSD 处理器正确地验证了XHTML 模式。所以这不是 .NET XSD 处理器问题,而是 xsd.exe 所依赖的 .NET 其他部分的问题(更具体地说,它是 xsd.exe 进行的外部调用,XmlSchemaImporter.ImportTypeMapping 失败惨)

    我会责怪规范不够清晰,以避免这种混淆,在我看来,部分归咎于主流产品的行为不端。

    【讨论】:

    • “除非您修复该文件(我们曾经为客户做过一次),否则您将无法摆脱这些错误” - 您能澄清一下吗?一个 div 可以包含一个 div。我不知道如何修复文件并仍然描述有效的 xhtml?
    • 关于 XSD 规范中的注释,这里没有正确解释 - 请参阅 lists.w3.org/Archives/Public/xmlschema-dev/2007Mar/0032.html
    • @GrahameGrieve,感谢您提供这些参考资料;我已经澄清了我的答案。 Michael 的回复与一个可以正常使用 xsd.exe 的测试用例有关。关于您的第一条评论,我不确定我是否理解 div 部分;至于修复,只有当您的解决方案依赖于 XmlSchemaImporter 时,您才需要这样做。我们专注于 XML Schema Refactoring,因此作为对我们的客户的服务,他们的工具不支持以语法运行(就像 xhtml1-strict.xsd 和 xsd.exe 一样),我们发布了等效 XSD(内部使用)没有麻烦的位。
    • 规范如何更清晰?我想我们可以添加一条注释:“不要使用 xsd.exe,因为它很笨”。而且我仍然不明白如何拥有对 xsd.exe 没有问题的等效架构。大概你不会澄清......
    • @GrahameGrieve,我们在这里谈论的是相同的规范吗?我指的是 W3C XML Schema 规范(XSD)——因为对它的解释是导致 xsd.exe 问题的原因,而不是 FHIR 标准(您似乎与之相关)。我指的修复是 xhtml1-strict XSD,而不是您的 OTHER 模式。如果您对不使用组的 xhtml1-strict 的 XSD 感兴趣,但它验证相同,请随时通过我网站上的支持地址直接与我联系。
    【解决方案4】:

    感谢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 cmets 上报告了这些发现,并希望它们能够得到解决。 与此同时,我可以继续我的初衷。使用这些定义的 API 的 SOAP 实现。

    【讨论】:

    • 您好 user824791....我们可以做些什么来使分发中生成的类更好地满足您的需求吗?例如。我也应该生成 Xml.Serialization 属性吗?什么可以使架构不那么不友好?
    • 您可以做的任何事情以使使用 xsd.exe 创建完整的类成为可能,这似乎是第一要务。接下来,这些类需要完全可序列化/可反序列化。 (到目前为止,patient.active.value 无法序列化,而 patient.active.id 可以。我不知道为什么。)整个过程应该是完全自动化的。单元测试将能够在发布之前验证诸如 patient.active.value 之类的问题。接下来在我看来,API 应该仅限于帮助构建和验证对象。
    • 只是我的看法,从设计 POV 来看,实体应该很简单。理想情况下,它们不应该有与序列化相关的方法,或协助处理结构(即 AndFamily 上 HumanName 和 Validate )。我个人犯了这个错误。授权应该是简单的 POCO,它们无需任何自定义代码(xml、soa 或 json 等)即可序列化。AndFamily 和 Validate 等方法在共享的工具包类中很有意义。由于模型的复杂性,这些都是必需的。
    • 重读此线程...生成的类非常干净。序列化方法分为 FhirSerializer 和 FhirParser 类。像 AndFamily 这样的辅助方法实际上并不在 HumanName 上,而是作为扩展方法添加到 - 确实 - 一个单独的工具包类的一部分。
    猜你喜欢
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 2011-02-06
    • 2019-09-08
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 2013-03-08
    相关资源
    最近更新 更多