4

一部の xsd スキーマ、特に置換グループ要素 (substitutiongroup) のデシリアライズ/シリアライズに問題があります。私がやりたいことは、xsd スキーマから C# クラスを生成し、オブジェクトで処理し、後でそれらを有効な XML 形式にシリアル化することです。xsd2code または xsd.exe でデシリアライズおよびシリアライズする 4 つの xsd ファイルがあります。どちらのツールも同様の不満足な結果を生成します。これらは「substitutiongroup」要素を無視し、クラス メンバーを適切に生成しません。xsd.exe または xsd2code を実行すると、たとえば BPMNPlane 用に生成された c# クラスにはメンバー BPMNShape が含まれません (ただし、BPMNDiagram クラスには BPMNPlane が含まれます)。生成された C# クラスを変更しようとしましたが (メンバー/プロパティの追加など)、生成された XML 出力が正しくありませんでした。linq-to-xml でこれをマスターできると思いますが、

<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 の経験はありませんが、強く型付けされたデータ/オブジェクトを操作するには、より良いアプローチだと思いますか?

4

3 に答える 3

6

まず、私はあなたの質問に賛成票を投じました。なぜなら、それは本当にまれなシナリオをもたらしたからです - それはまた、何人の人がそれを伝えたかから判断すると、答えるのに苦労しました...つまり、あなたはいくつかの読書をしなければならないでしょう:) ...

簡単に言えば、xsd.exe は使用可能なコードを作成します。それはあなたが期待したものではないかもしれません。その理由を説明しますが、動作します (少なくとも私のテストでは)。その XML の交換に問題がない場合は、生成された方法でそのまま使用してください。そうでない場合、Linq は確実に機能します。

したがって、主な問題は、XML スキーマがどのように作成されたかから始まります。それがどこから来ているのかを考えると、オーサリング スタイルにこの (認識された) あいまいさが見られることに驚きました。これは、最終的に xsd.exe が期待どおりの結果をもたらさないように見える理由の原因でもあります。

「抽象属性」および「SubstitutionGroup属性」という名前のセクションに焦点を当てて、このペーパーを読むことから始めてください。

通常、置換グループの先頭は抽象要素であると想定されています。これは仕様によって強制されていませんが、ツール (xsd.exe がその 1 つ) でこの仮定を行う人が多いのではないかと思います。

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 型から派生する任意の型を取り込み、基本的にコントラクトを満たします (生成された 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 の代わりに他に何を配置するかを考え出すことだけです。私はそれを描くためにこのグラフを使用しました:

ここに画像の説明を入力

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

このスキーマは、1 つのスキーマのみを使用して (xsi:type オーサリング スタイルの有無にかかわらず) 両方の方法で実現できることを示す完璧な例だと思います。この後者の XML が xsd.exe によって生成されたコードを使用して逆シリアル化できるかどうか、およびそれを機能させるためにどのような変更を行う必要があるかを確認することは、優れたテストになる可能性があります。

于 2011-11-24T02:31:13.577 に答える