使用xsd.exe或xsd2code反序列化复杂的xsd模式(包含用于继承的substitutiongroup元素)

use*_*993 4 serialization xsd linq-to-xml xsd2code deserialization

我在反序列化/序列化某些xsd模式时遇到问题,特别是在其中使用了替换组元素(substitutiongroup).我想要做的是从xsd架构生成C#类,然后处理对象,然后将它们序列化为有效的XML格式.有4个xsd文件,我用xsd2code或xsd.exe反序列化和序列化.这两种工具都会产生类似的不满意结果.它们忽略"substitutiongroup"元素,并且不会正确生成类成员.当我运行xsd.exe或xsd2code时,为BPMNPlane生成的c#类例如不包含成员BPMNShape(但BPMNDiagram类包含BPMNPlane).我试图更改生成的C#类(例如添加成员/属性),但生成的XML输出不正确.我想人们可以用linq-to-xml来掌握它,但它们是太多不同的元素,大约70,具有额外的属性属性.

<xsd:import namespace="http://www.omg.org/spec/DD/20100524/DC" schemaLocation="DC.xsd" />
<xsd:import namespace="http://www.omg.org/spec/DD/20100524/DI" schemaLocation="DI.xsd" />

<xsd:element name="BPMNDiagram" type="bpmndi:BPMNDiagram" />
<xsd:element name="BPMNPlane" type="bpmndi:BPMNPlane" />
<xsd:element name="BPMNLabelStyle" type="bpmndi:BPMNLabelStyle" />
<xsd:element name="BPMNShape" type="bpmndi:BPMNShape" substitutionGroup="di:DiagramElement" />
<xsd:element name="BPMNLabel" type="bpmndi:BPMNLabel" />
<xsd:element name="BPMNEdge" type="bpmndi:BPMNEdge" substitutionGroup="di:DiagramElement" />

<xsd:complexType name="BPMNDiagram">
    <xsd:complexContent>
        <xsd:extension base="di:Diagram">
            <xsd:sequence>
                <xsd:element ref="bpmndi:BPMNPlane" />
                <xsd:element ref="bpmndi:BPMNLabelStyle" maxOccurs="unbounded" minOccurs="0" />
            </xsd:sequence>
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>


<xsd:complexType name="BPMNPlane">
    <xsd:complexContent>
        <xsd:extension base="di:Plane">    
    <xsd:attribute name="bpmnElement" type="xsd:QName" />       
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="BPMNEdge">
    <xsd:complexContent>
        <xsd:extension base="di:LabeledEdge">
            <xsd:sequence>
                <xsd:element ref="bpmndi:BPMNLabel" minOccurs="0" />
            </xsd:sequence>
            <xsd:attribute name="bpmnElement" type="xsd:QName" />
            <xsd:attribute name="sourceElement" type="xsd:QName" />
            <xsd:attribute name="targetElement" type="xsd:QName" />
            <xsd:attribute name="messageVisibleKind" type="bpmndi:MessageVisibleKind" />
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>



<xsd:complexType name="BPMNShape">
    <xsd:complexContent>
        <xsd:extension base="di:LabeledShape">
            <xsd:sequence>
                <xsd:element ref="bpmndi:BPMNLabel" minOccurs="0" />
            </xsd:sequence>
            <xsd:attribute name="bpmnElement" type="xsd:QName" />
            <xsd:attribute name="isHorizontal" type="xsd:boolean" />
            <xsd:attribute name="isExpanded" type="xsd:boolean" />
            <xsd:attribute name="isMarkerVisible" type="xsd:boolean" />
            <xsd:attribute name="isMessageVisible" type="xsd:boolean" />
            <xsd:attribute name="participantBandKind" type="bpmndi:ParticipantBandKind" />
            <xsd:attribute name="choreographyActivityShape" type="xsd:QName"/>
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="BPMNLabel">
    <xsd:complexContent>
        <xsd:extension base="di:Label">
            <xsd:attribute name="labelStyle" type="xsd:QName" />
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>

<xsd:complexType name="BPMNLabelStyle">
    <xsd:complexContent>
        <xsd:extension base="di:Style">
            <xsd:sequence>
                <xsd:element ref="dc:Font" />
            </xsd:sequence>
        </xsd:extension>
    </xsd:complexContent>
</xsd:complexType>

<xsd:simpleType name="ParticipantBandKind">
    <xsd:restriction base="xsd:string">
        <xsd:enumeration value="top_initiating" />
        <xsd:enumeration value="middle_initiating" />
        <xsd:enumeration value="bottom_initiating" />
        <xsd:enumeration value="top_non_initiating" />
        <xsd:enumeration value="middle_non_initiating" />
        <xsd:enumeration value="bottom_non_initiating" />
    </xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="MessageVisibleKind">
    <xsd:restriction base="xsd:string">
        <xsd:enumeration value="initiating" />
        <xsd:enumeration value="non_initiating" />
    </xsd:restriction>
</xsd:simpleType>
Run Code Online (Sandbox Code Playgroud)

我是新手,并没有使用xsd或linq-to-xml的经验,但我认为这是使用强类型数据/对象的更好方法?

Pet*_*dea 5

首先,我提出了你的问题,因为它确实带来了一个罕见的情况 - 它也很难被回答,根据有多少人传递它...这也意味着你将不得不做一些阅读:) ...

简短的回答是:xsd.exe创建可用的代码; 它可能不是你所期望的,我会解释原因,但它有效(至少我的测试); 如果你没有交换那个XML的问题,那么就像它生成它一样.如果没有,那么Linq肯定会工作.

因此,主要问题始于XML Schema的编写方式; 考虑到它来自哪里,我很惊讶地看到这种(感知的)创作风格的模糊性,这最终也是为什么xsd.exe似乎没有产生预期结果的原因.

请从阅读本文开始,重点关注名为"抽象属性"和"替换组属性"的部分.

通常,替换组的头部应该是抽象元素.虽然规范没有强制执行,但我怀疑很多人在他们的工具中做出这个假设(xsd.exe是一个)因为否则存在与@xsi:type模糊的风险.

在BPMN模式中,替换组的头部不是抽象的(我看过的那个); 更多,用作替换组头部的元素是抽象类型 - 这在xsi:type中响起.总而言之,如果你看看生成的代码,xsd.exe会创建一个完全有效的代码,通过选择使用或不使用xsi:type; 它和前者一起去了.

此代码引用xsd.exe生成的代码来创建简单的XML.

BPMNEdge edge = new BPMNEdge();
edge.id = "B2";
// more code here for waypoint
plane.DiagramElement1 = new DiagramElement[] { edge };
Run Code Online (Sandbox Code Playgroud)

DiagramElement1属性基本上将采用从DiagramElement类型派生的任何类型,基本上完全填充契约(并为生成的XML中的DiagramElement提供@xsi:类型).

下面的XML是有效的; 我无法弄清楚是否使用DiagramElement摘要来解决你的问题...我不认为它可能会那么简单,但我会留给你.

<?xml version="1.0" encoding="utf-16"?>
<BPMNPlane xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="A1" xmlns:q1="urn:tempuri-org:alpha" bpmnElement="q1:test" xmlns="http://www.omg.org/spec/BPMN/20100524/DI">
  <DiagramElement xmlns:q2="http://www.omg.org/spec/BPMN/20100524/DI" xsi:type="q2:BPMNEdge" id="B2" xmlns="http://www.omg.org/spec/DD/20100524/DI">
    <waypoint x="1" y="1" />
    <waypoint x="1" y="1" />
</DiagramElement>
</BPMNPlane> 
Run Code Online (Sandbox Code Playgroud)

下面的(也是有效的)XML是由工具生成的(不是由xsd.exe生成的代码); 它显示了一个完全有效的上述XML替代方案,使用替换组的成员,这是你想要的.您所要做的就是找出替代DiagramElement的其他内容.我用这个图来描绘它:

在此输入图像描述

<?xml version="1.0" encoding="utf-16"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<BPMNPlane xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="A1" xmlns:q1="urn:tempuri-org:alpha" bpmnElement="q1:test" xmlns="http://www.omg.org/spec/BPMN/20100524/DI">
    <BPMNEdge xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" p4:any_Attr="anySimpleType" bpmnElement="qname1" sourceElement="qname1" targetElement="qname1" messageVisibleKind="initiating" id="ID1" xmlns:p4="otherNS" xmlns="http://www.omg.org/spec/BPMN/20100524/DI">
        <di:extension/>
        <di:waypoint x="1" y="1"/>
        <di:waypoint x="-1.7976931348623157E+308" y="-1.7976931348623157E+308"/>
        <BPMNLabel p4:any_Attr="anySimpleType" labelStyle="qname1" id="ID2">
            <di:extension/>
            <dc:Bounds x="1" y="1" width="1" height="1"/>
        </BPMNLabel>
    </BPMNEdge>
</BPMNPlane>
Run Code Online (Sandbox Code Playgroud)

我认为这个模式是一个完美的例子,它展示了如何使用一个模式(无论有没有xsi:类型创作风格)可以同时拥有它.一个很好的测试可能是看看后面的XML是否可以使用xsd.exe生成的代码进行反序列化,以及为了使其工作需要进行哪些更改.