2011-04-11 65 views
1

的阵列我有像这样的列表的XML文件:xml元素列表,以共同的基本类型

<TestFile> 
    <string>Foo</string> 
    <bool>false</bool> 
    <bool>true</bool> 
    <string>Bar</string> 
</TestFile> 

我想将其反序列化到类型的数组“值”。该类型有两个子类型“ValueString”和“ValueBool”:

[XmlRoot("TestFile")] 
public class TestFile 
{ 
    public List<Test> Tests; 
} 

public class Value 
{ 
} 

public class ValueString : Value 
{ 
    [XmlText] 
    public string Value; 
} 

public class ValueBool : Value 
{ 
    [XmlText] 
    public bool Value; 
} 

我想不出如何做到这一点。我试过XmlIncludeAttributes,但它不够,因为元素名称与类名称不匹配。我试过XmlChoiceIdentifier,但我发现的例子在编辑时不能编译...

我需要保留元素的顺序,因此将元素分成两个列表将不起作用。我也不能更改xml结构,因为它来自外部源。显然,这只是一个例子 - 我真正的类型比较复杂......

+0

个人而言,我建议您编写自己的xml解析代码,因为xml序列化实际上并不是用来读取xml的一种方式。 – juharr 2011-04-11 13:29:10

回答

2

我终于绊了解决方案:

[XmlRoot("TestFile")] 
public class TestFile 
{ 
    [XmlElement(ElementName = "string", Type = typeof(ValueString))] 
    [XmlElement(ElementName = "bool", Type = typeof(ValueBool))] 
    public List<Test> Tests; 
} 

我以为我试过,以前......好吧,至少现在的工作。这个例子还有另外一个问题:你不能有一个布尔字段映射到一个元素文本,但是这个特定问题在我的真实场景中不存在...

2

通常我们发现自己不得不改变给我们的XML文件。是的,如果每个人都赞同相同的结构,那将是非常好的,但在中型到大型公司中这可能更难实现。

我开始使用XML文件:

<?xml version="1.0" encoding="utf-8" ?> 
<TestFile> 
    <string>Foo</string> 
    <bool>false</bool> 
    <bool>true</bool> 
    <string>Bar</string> 
</TestFile> 

然后创建的转换文件(这只是一个例子,一切都取决于你自己的喜好):

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="@* | node()"> 
     <xsl:copy> 
     <ParameterCollection> 
      <xsl:apply-templates select="@* | node()"/> 
     </ParameterCollection> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="bool"> 
    <Parameter type="bool"> 
     <xsl:apply-templates select="node()"/> 
    </Parameter> 
    </xsl:template> 
    <xsl:template match="string"> 
    <Parameter type="string"> 
     <xsl:apply-templates select="node()"/> 
    </Parameter> 
    </xsl:template> 
</xsl:stylesheet> 

然后,我开始拼凑所有必要的课程在一起:

[XmlRootAttribute("TestFile", IsNullable = false)] 
public class TestFile 
{ 
    [XmlArrayAttribute("ParameterCollection")] 
    public Parameter[] Parameters; 
} 

public class Parameter 
{ 
    [XmlAttribute("type")] 
    public string ObjectType; 

    [XmlText] 
    public string ObjectValue; 
} 

然后应用一切(希望在一个更多的想法比我已经完成的方式):

class Program 
{ 
    static void Main(string[] args) 
    { 
     FileInfo xmlFile = new FileInfo(@"Resources\TestFile.xml"); 
     FileInfo transformFile = new FileInfo(@"Resources\TestFileTransform.xslt"); 
     FileInfo prettyFile = new FileInfo(@"Resources\PrettyFile.xml"); 

     if (xmlFile.Exists && transformFile.Exists) 
     { 
      // Perform transform operations. 
      XslCompiledTransform trans = new XslCompiledTransform(); 
      trans.Load(transformFile.FullName); 
      trans.Transform(xmlFile.FullName, prettyFile.FullName); 
     } 

     if (prettyFile.Exists) 
     { 
      // Deserialize the new information. 
      XmlSerializer serializer = new XmlSerializer(typeof(TestFile)); 
      XDocument doc = XDocument.Load(prettyFile.FullName); 
      TestFile o = (TestFile)serializer.Deserialize(doc.CreateReader()); 

      // Show the results. 
      foreach (Parameter p in o.Parameters) 
      { 
       Console.WriteLine("{0}: {1}", p.ObjectType, p.ObjectValue); 
      } 
     } 

     // Pause for effect. 
     Console.ReadKey(); 
    } 
} 

希望这可以帮助某人,或者至少给他们另一种选择。通常,恕我直言,我宁愿解析文件或流,但那只是我。

相关问题