0

XML を使用可能なオブジェクト グラフに逆シリアル化しようとしています。私たちのシステムでオブジェクト構造を生成できるツールができるようになるまでにはしばらく時間がかかるので、できるだけ人間が XML を書き込めるようにしたいと考えています。

私が探しているのは、このような XML です

<RuleSet>
  <Conditions>
    <AttributeEqualTo>
      <Id>C1</Id>
      <AttributeName>Foo</AttributeName>
      <ExpectedValue>Bar</ExpectedValue>
    </AttributeEqualTo>
    <AttributeNotEqualTo>
      <Id>C2</Id>
      <AttributeName>Blah</AttributeName>
      <ExpectedValue>Value</ExpectedValue>
    </AttributeNotEqualTo>
  </Conditions>
  <States>
    <State>
      <Id>Start</Id>
      <Transitions>
        <Transition>
            <Condition>C1</Condition>
            <State>S1</State>
        </Transition>
        <Transition>
            <Condition>C2</Condition>
            <State>S2</State>
        </Transition>
      </Transitions>
    </State>
    <State>
      <Id>S1</Id>
      <Transitions>
        <Transition>
            <Condition>C2</Condition>
            <State>S2</State>
        </Transition>
      </Transitions>
    </State>
    <State>
      <Id>S2</Id>
    </State>
  </States>
</RuleSet>

私が探しているのは、Enumerable of Conditions と Enumerble of States を持つ RuleSet オブジェクトを含むオブジェクト グラフです。各状態には、以前に定義された条件、RuleSet の条件、および別の状態で作成された Enumerable の遷移があります。

独自のカスタム パーサーを作成する代わりに、誰かが既に作成した C# の XML パーサーを使用して、これを行う簡単な方法はありますか?

最初の回答から、もう少し明確にする必要があると思います。重複を減らすために参照を維持する設定をオンにして、オブジェクト グラフの単純なバージョンをシリアル化しようとしたとき。私は以下を受け取りました:

<RuleSet z:Id="1" >
    <Conditions z:Id="2" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <a:anyType z:Id="3" i:type="b:AttributeEqualTo" >
            <b:AttributeName z:Id="4">Foo</b:AttributeName>
            <b:ExpectedValue z:Id="5" i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">Bar</b:ExpectedValue>
            <b:Id z:Id="6">C1</b:Id>
        </a:anyType>
        <a:anyType z:Id="7" i:type="b:AttributeEqualTo" >
            <b:AttributeName z:Ref="5" i:nil="true"/>
            <b:ExpectedValue z:Ref="4" i:nil="true"/>
            <b:Id z:Id="8">C2</b:Id>
        </a:anyType>
    </Conditions>
    <States z:Id="9" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <a:anyType z:Id="10" i:type="b:State" >
            <b:EntryActions z:Id="11"/>
            <b:Id z:Id="12">S1</b:Id>
            <b:Transitions z:Id="13" z:Size="2">
                <a:anyType z:Id="14" i:type="c:Transition" >
                    <c:Condition z:Ref="3" i:nil="true"/>
                    <c:Next z:Id="15" i:type="b:State">
                        <b:EntryActions z:Id="16"/>
                        <b:Id z:Id="17">S2</b:Id>
                        <b:Transitions z:Id="18" z:Size="1">
                            <a:anyType z:Id="19" i:type="c:Transition">
                                <c:Condition z:Ref="7" i:nil="true"/>
                                <c:Next z:Id="20" i:type="b:State">
                                    <b:EntryActions z:Id="21"/>
                                    <b:Id z:Id="22">S3</b:Id>
                                    <b:Transitions z:Id="23" z:Size="0"/>
                                </c:Next>
                            </a:anyType>
                        </b:Transitions>
                    </c:Next>
                </a:anyType>
                <a:anyType z:Id="24" i:type="c:Transition" >
                    <c:Condition z:Ref="7" i:nil="true"/>
                    <c:Next z:Ref="20" i:nil="true"/>
                </a:anyType>
            </b:Transitions>
        </a:anyType>
        <a:anyType z:Ref="15" i:nil="true"/>
        <a:anyType z:Ref="20" i:nil="true"/>
    </States>
</RuleSet>

私がやろうとしているのは、 z:Id="x" と z:Ref="x" を独自の Id プロパティの使用法に置き換えることです。繰り返しますが、システムをより人間が書き込み可能にするためです。C# クラスで属性を設定して、タグの名前を変更する方法がわかります。

4

3 に答える 3

2

独自のパーサーを作成する必要はありません。Xml シリアライゼーション属性をクラスに適用して、シリアライゼーションとデシリアライゼーションのプロセスを制御できます。または、Linq to Xml などの既存のパーサーを使用することもできます。

Xml シリアル化属性の使用例を次に示します。

public class RuleSet
{
    [XmlArrayItem(typeof(AttributeEqualTo))]
    [XmlArrayItem(typeof(AttributeNotEqualTo))]
    public List<Condition> Conditions { get; set; }
}

public class Condition
{
    public string Id { get; set; }
    public string AttributeName { get; set; }
    public string ExpectedValue { get; set; }
}

public class AttributeEqualTo : Condition
{
    // code
}

public class AttributeNotEqualTo : Condition
{
    // code
}

そして逆シリアル化:

XmlSerializer serializer = new XmlSerializer(typeof(RuleSet));
RuleSet ruleSet = (RuleSet)serializer.Deserialize(stream_with_xml);

同じアプローチを使用して状態を逆シリアル化します。

于 2013-01-16T15:42:31.190 に答える
0

これにはXmlSerializerを使用できます。また、目的の XML に XML 属性がない場合は、NetDataContractSerializer を使用することもできます( DataContractSerializer は属性の発行をサポートしていません - 要素のみ)。

いずれにせよ、C# クラスに属性 (XmlAttributes、または DataMember 属性) を付けて、必要に応じて正確にシリアル化できるようにする必要があるでしょう。

于 2013-01-16T15:48:54.897 に答える
0

まず、シリアル化 (デ) されるオブジェクトは、クラスまたは構造体のいずれかです。System.Xml と System.Xml.Serialization を含む using ステートメントが必要です (私の頭の上から)。

次に、このクラス/構造体宣言を [Serializable] 属性で装飾する必要があります。XML 要素としてシリアル化する場合は [XmlElement]、シリアル化されたクラスの XML 属性にする場合は [XmlAttribute] などの対応する属性で、シリアル化 (非) 化する各パブリック プロパティとメソッドを装飾します。 /構造体。

また、クラスにパラメーターなしのコンストラクターがあることを確認してください。そうしないと、シリアル化が失敗します。

最後になりましたが、XmlSerializer/XmlDeserializer を使用して生成/解析します。カスタム XML 解析を作成する時代は終わりました。これは間違いなく、大幅な時間の節約になります。

于 2013-01-16T15:56:10.353 に答える