Destroying complex xsd schemes (containing wildcard elements for inheritance) using xsd.exe or xsd2code

I have problems deserializing / serializing some xsd schemes, especially with elements of the substitution group inside. I want to create C # classes from xsd schemas, then process the object and then serialize them into a valid XML format. There are 4 xsd files that I deserialize and serialize using xsd2code or xsd.exe. Both tools generate similar unsatisfactory results. They ignore substitutiongroup elements and do not generate class members properly. When I run xsd.exe or xsd2code, the generated C # class for BPMNPlane, for example, does not contain a BPMNShape member (however, the BPMNDiagram class contains BPMNPlane). I tried changing the generated C # classes (e.g. add members / properties), but the generated XML output was wrong. I suppose this can be implemented using linq-to-xml, but they represent too many different elements, about 70, with additional property attributes.

<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> 

I am new and have no experience with xsd or linq-to-xml, but I think this is the best approach to working with strongly typed data / objects?

+4
source share
2 answers

Firstly, I raised your question, because it really causes a rare scenario - it was also not easy to answer, judging by how many people transmit it ... Which also means that you will need to do some reading :). ..

Short answer: xsd.exe creates useful code; perhaps this is not how you expected, and I will explain why, but it works (at least with my tests); if you have no problem exchanging this XML, and not just with it, how it is created. If not, then Linq will work for sure.

So, the main problem starts with how the XML schema was created; given that it comes from I was surprised to see this (perceived) ambiguity in the authorship style, which is ultimately also responsible for why xsd.exe does not seem to give the expected result.

Please start by reading this article with a focus on the Abstract Attribute and SubstitutionGroup Attributes.

Usually the leader of a substitution group should be an abstract element. Although this does not meet the specification, I suspect that many people make this assumption in their tool (xsd.exe is one), as otherwise there is a risk of ambiguity with the @xsi: type type.

In the BPMN scheme, the leader of the replacement groups is not abstract (the one I was looking at); Moreover, the elements used as the head of the substitution group have an abstract type - these are rings in xsi: type. In short, if you look at the generated code, xsd.exe creates the right code, choosing between using or not using xsi: type; he went with the first.

This code refers to the generated xsd.exe code to create simple XML.

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

The DiagramElement1 property will basically accept any type that is inferred from the DiagramElement type, basically populating the contract (and providing you with the @xsi: type for DiagramElement in the generated XML).

Assume XML below; I could not understand if the DiagramElement essay would help solve your problem ... I don’t think it could be that simple, but I will leave it to you.

 <?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> 

The (also valid) XML below was generated by a tool (not the code generated by xsd.exe); it shows a perfectly valid alternative to the above XML, using the members of the replacement group that you wanted. All you have to do is figure out what else is in place of the DiagramElement. I used this graph to view it:

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> 

I think this scheme is a great example that shows how one could use both methods (with or without xsi: type authoring style) using only one scheme. A great test may be to see if this last XML can be deserialized using the code generated by xsd.exe, and what changes will need to be made to make it work.

+5
source

Thank you for your time! This is a good explanation! I also found that this is:

 BPMNDiagram bpmnd = new BPMNDiagram(); BPMNPlane bpmnl = bpmnd.BPMNPlane; bpmnl.DiagramElement1.Add(new BPMNShape()); 

works, it gives me the following XML structure:

But I really want:

 <bpmndi: BPMNDiagram name="bpmndiagramid"> <bpmndi: BPMNPlane> <bpmndi:BPMNShape id="11" bpmnElement="functionsname"> <dc:Bounds x="0" y="0" width="0" height="0"/> </bpmndi:BPMNShape> </bpmndi: BPMNPlane> </bpmndi: BPMNDiagram > 

So, I can write:

 BPMNDiagram bpmnd = new BPMNDiagram(); BPMNPlane bpmnl = bpmnd.BPMNPlane; 

which gives me:

 < BPMNDiagram name="bpmndiagramid"> < BPMNPlane>... </ BPMNPlane> </ BPMNDiagram > 

But not directly this:

 BPMNDiagram bpmnd = new BPMNDiagram(); BPMNPlane bpmnl = bpmnd.BPMNPlane; BPMNShape myShape = bpmnl.BPMNShape; 

I thought that it would be faster than working with LINQ 2 XML, generating C # classes and working with them, but now I see that I need to understand XML Schema / Elements, etc. more deeply.

0
source

Source: https://habr.com/ru/post/1382253/


All Articles