gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 07:29:01 25 4
gpt4 key购买 nike

我在反序列化/序列化某些 xsd 模式时遇到问题,特别是其中的替换组元素(substitutiongroup)。我想要做的是从 xsd 模式生成 C# 类,然后处理对象,然后将它们序列化为有效的 XML 格式。
我使用 xsd2code 或 xsd.exe 反序列化和序列化了 4 个 xsd 文件。这两种工具都会产生类似的不尽人意的结果。他们忽略“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>

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

最佳答案

首先,我赞成你的问题,因为它确实带来了一个罕见的场景——它也很难得到回答,从有多少人通过它来判断......这也意味着你必须做一些阅读:) ...

简短的回答是:xsd.exe 创建可用的代码;它可能不是你所期望的,我会解释原因,但它有效(至少在我的测试中);如果您在交换 XML 时没有问题,那么只需按照它的生成方式进行即可。如果没有,Linq 肯定会工作。

因此,主要问题始于 XML Schema 的编写方式;考虑在哪里it is coming from我很惊讶地看到创作风格中的这种(感知到的)歧义,这最终也是为什么 xsd.exe 似乎没有产生您预期的结果的原因。

请先阅读 this paper ,重点介绍名为“Abstract Attribute”和“SubstitutionGroup Attribute”的部分。

通常,替换组的头应该是一个抽象元素。虽然这不是规范强制执行的,但我怀疑很多人在他们的工具中做出了这个假设(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 };

DiagramElement1 属性将基本上接受从 DiagramElement 类型派生的任何类型,基本上完成契约(Contract)(并在生成的 XML 中为您提供 DiagramElement 的 @xsi:type)。

下面的 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>

下面的(也是有效的)XML 是由工具生成的(不是由 xsd.exe 生成的代码);它显示了一个完全有效的替代上述 XML 的方法,使用替换组的成员,这正是您想要的。您所要做的就是弄清楚还有什么可以代替DiagramElement。我用这张图来描绘它:

enter image description here
<?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>

我认为这个模式是一个完美的例子,它展示了如何只使用一种模式来实现两种方式(有或没有 xsi:type 创作风格)。一个很好的测试可能是查看是否可以使用 xsd.exe 生成的代码反序列化后一个 XML,以及需要进行哪些更改才能使其工作。

关于serialization - 使用 xsd.exe 或 xsd2code 反序列化复杂的 xsd 模式(包含用于继承的替换组元素),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8210717/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com