2017-06-02 6 views
2

私は、データプロバイダによって私たちに与えられたXSDスキーマを持っています。私はそれを変更することはできません。 XSD.exeコマンドラインツールを使用してクラスを生成しました。それが完璧に動作するためには、C#でオブジェクトを作成し、XMLでシリアル化し、XSDに対して検証します。C#でXMLシリアル化を行う際にXML要素をどのように置き換えるのですか?

私は小さな部分に問題があります。予想される出力は次のようになります。

<Physical> 
     <Class>P</Class> 
     <Capacity>14</Capacity> 
     <Class>J</Class> 
     <Capacity>64</Capacity> 
     <Class>W</Class> 
     <Capacity>1</Capacity> 
     <Class>Y</Class> 
     <Capacity>2</Capacity> 
    </Physical> 
    <Saleable Protected="true"> 
     <Class>P</Class> 
     <Capacity>14</Capacity> 
     <Class>J</Class> 
     <Capacity>64</Capacity> 
     <Class>W</Class> 
     <Capacity>1</Capacity> 
     <Class>Y</Class> 
     <Capacity>2</Capacity> 
    </Saleable> 

あなたが見ることができるように、物理的な密封可能な代替の子要素(その後、容量、そしてクラス、そして容量などつまりクラス)。

これは、Xsd.exeではにより生成されたクラスのコードです:

public partial class ClassA 
{ 
    private string[] classField; 

    private Integerctype[] capacityField; 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute("Class", DataType = "token")] 
    public string[] Class 
    { 
     get 
     { 
      return this.classField; 
     } 
     set 
     { 
      this.classField = value; 
     } 
    } 

    /// <remarks/> 
    [System.Xml.Serialization.XmlElementAttribute("Capacity", IsNullable = true)] 
    public Integerctype[] Capacity 
    { 
     get 
     { 
      return this.capacityField; 
     } 
     set 
     { 
      this.capacityField = value; 
     } 
    } 
} 

そして、私はシリアル化後受信出力:

<Physical> 
    <Class>P</Class> 
    <Class>J</Class> 
    <Class>W</Class> 
    <Class>Y</Class> 
    <Capacity>14</Capacity> 
    <Capacity>64</Capacity> 
    <Capacity>1</Capacity> 
    <Capacity>2</Capacity> 
</Physical> 
<Saleable> 
    <Class>P</Class> 
    <Class>J</Class> 
    <Class>W</Class> 
    <Class>Y</Class> 
    <Capacity>14</Capacity> 
    <Capacity>64</Capacity> 
    <Capacity>1</Capacity> 
    <Capacity>2</Capacity> 
</Saleable> 

あなたが見ることができるように、私たちは失われましたクラスとキャパシティの交代...

私はXmlElementAttributeのOrderプロパティを使用しようとしました:ClassプロパティはOrder = 1で装飾され、CapacityプロパティはdecoでしたOrder = 2と評価されましたが、それは役に立たなかった。例:検証中に

[System.Xml.Serialization.XmlElementAttribute("Class", DataType = "token", Order = 1)] 
public string[] Class 

は、Orderプロパティの有無にかかわらず、私は次のようにエラーが表示さ:

の要素の名前空間の「物理」「xxxは」に無効な子要素 「クラス」を持っています名前空間 'xxx'にあります。可能な要素のリスト: '容量'名前空間 'xxx'。

最後に、ここでXSDの一部です:シーケンス:

<xsd:element name="ClassA" minOccurs="0"> 
    <xsd:complexType> 
     <xsd:all> 
      <xsd:element name="Physical" minOccurs="0"> 
       <xsd:annotation> 
        <xsd:documentation>True, physical class A configuration</xsd:documentation> 
       </xsd:annotation> 
       <xsd:complexType> 
        <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
         <xsd:element name="Class" type="CabinClass.type" /> 
         <xsd:element name="Capacity" type="Integer.ctype" nillable="true" /> 
        </xsd:sequence> 
        <xsd:attributeGroup ref="Array.attgroup" /> 
       </xsd:complexType> 
      </xsd:element> 
      <xsd:element name="Saleable" minOccurs="0"> 
       <xsd:annotation> 
        <xsd:documentation>Class A configuration for sales purposes</xsd:documentation> 
       </xsd:annotation> 
       <xsd:complexType> 
        <xsd:sequence minOccurs="0" maxOccurs="unbounded"> 
         <xsd:element name="Class" type="CabinClass.type" /> 
         <xsd:element name="Capacity" type="Integer.ctype" nillable="true" /> 
        </xsd:sequence> 
        <xsd:attributeGroup ref="Array.attgroup" /> 
       </xsd:complexType> 
      </xsd:element> 
     </xsd:all> 
     <xsd:attributeGroup ref="Container.attgroup" /> 
    </xsd:complexType> 
</xsd:element> 

私の推測では、それがXSDの存在に関連していることです。しかし、私が言ったように、私はXSDをデータプロバイダが提供するように変更したくないので、生成するXMLが完全に互換性があることを確認する必要があります。

どうすればこの問題を解決できますか?これは、正しいデシリアライズを確実にし、それらがアレイ状に配置された順序で要素のシリアライズを与える

public class Physical 
{ 
    [XmlElement("Capacity", typeof(int))] 
    [XmlElement("Class", typeof(string))] 
    public object[] Items { get; set; } 
} 

+0

オーダーはxmlと違いはありませんが、スキーマの問題のためオーダーはあなたのケースで非常に重要です。順序を保証する最も良い方法は、XDocumentまたはXmlDocumentメソッドのいずれかを使用してカスタムシリアル化を書き込むことです。XmlWriterを使用することもできます。 – jdweng

+0

@jdweng、あなたのご意見ありがとうございます。はい、それはこれらの要素が正確な順序であることを期待しているのは変ですが、それは残念なことに方法です。 XSDと生成されたXMLファイルは膨大なので、おそらくカスタムシリアライザが最適なオプションではありません。私たちは標準的なシリアライゼーションを使い、XSD.exeによって生成されたクラスを簡単にするために必要なところでのみカスタマイズしようとしています。 – DotNetMatt

+0

ファイルが巨大な場合は、標準シリアル化を使用してメモリ不足エラーが発生する可能性があります。したがって、XmlReaderを使用する必要があります。他の選択肢はありません。 – jdweng

答えて

1

簡易コードは、このかもしれません。 、

public class Physical 
{ 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    [XmlElement("Capacity", typeof(int))] 
    [XmlElement("Class", typeof(string))] 
    public object[] Items 
    { 
     get 
     { 
      object[] items = new object[Class.Length * 2]; 
      for (int i = 0; i < items.Length; i += 2) 
      { 
       items[i] = Class[i/2]; 
       items[i + 1] = Capacity[i/2]; 
      } 
      return items; 
     } 
     set 
     { 
      Class = new string[value.Length/2]; 
      Capacity = new int[value.Length/2]; 
      for (int i = 0; i < value.Length; i += 2) 
      { 
       Class[i/2] = (string)value[i]; 
       Capacity[i/2] = (int)value[i + 1]; 
      } 
     } 
    } 

    [XmlIgnore] 
    public string[] Class { get; set; } 
    [XmlIgnore] 
    public int[] Capacity { get; set; } 
} 

変更intIntegerctypeからDataTypeのパラメータを追加します。

A作業バージョンは、次のようになります。

同様に、2番目のクラスを変更します。

+0

アレクサンダーありがとう、それは魅力のように動作します! – DotNetMatt

関連する問題