我试图将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>
我正在寻找的是一个对象图,它包含一个RuleSet对象,该对象具有Enumerable of Conditions和Enumerble of States。每个State都有一个Enumerable of Transitions,它由先前在RuleSet条件和另一个州中定义的条件组成。
有没有一种简单的方法可以做到这一点,因为在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>
我要做的是用我自己的Id属性的用法替换z:Id =“x”和z:Ref =“x”。再次使系统更加人性化。我看到如何通过在C#类中设置属性来更改标记的名称。
答案 0 :(得分:2)
您不需要编写自己的解析器。您可以将Xml序列化属性应用于您的类,这将控制序列化和反序列化过程。或者你可以使用现有的解析器,比如Linq to Xml。
以下是Xml serialization attributes用法的示例:
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);
使用相同的方法反序列化状态。
答案 1 :(得分:0)
您可以使用XmlSerializer。 此外,假设您在所需的XML中没有任何XML属性,那么您也会使用NetDataContractSerializer(DataContractSerializer不支持发布属性 - 仅限元素)。
无论哪种方式,您可能需要使用属性(XmlAttributes或DataMember属性)来注释C#类,以使其根据需要进行精确序列化。
答案 2 :(得分:0)
首先,您要(de)序列化的对象是类或结构。您将需要一个using语句,包括System.Xml和System.Xml.Serialization(在我的脑海中)。
然后,您必须使用[Serializable]属性修饰此类/结构声明。 如果您希望将其序列化为XML元素,则装饰您希望(de)使用其相应属性(如[XmlElement])序列化的每个公共属性和方法;如果您希望它是序列化类的XML属性,则装饰[XmlAttribute] /结构
还要确保您的类具有无参数构造函数或序列化将失败。
最后但并非最不重要的是,使用XmlSerializer / XmlDeserializer来生成/解析。编写自定义XML解析的日子已经一去不复返了,这绝对是一个巨大的节省时间。