XML元素列表到公共基类型的数组
本文关键字:基类 类型 数组 元素 列表 XML | 更新日期: 2023-09-27 17:49:36
我有一个包含如下列表的xml文件:
<TestFile>
<string>Foo</string>
<bool>false</bool>
<bool>true</bool>
<string>Bar</string>
</TestFile>
我想将其反序列化为类型为"Value"的数组。该类型有两个子类型"ValueString"answers"valueool":
[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结构,因为它来自外部源。显然这只是一个例子,我真正的类型更复杂…
我终于找到了解决方案:
[XmlRoot("TestFile")]
public class TestFile
{
[XmlElement(ElementName = "string", Type = typeof(ValueString))]
[XmlElement(ElementName = "bool", Type = typeof(ValueBool))]
public List<Test> Tests;
}
我想我以前试过……好吧,至少现在还能用。这个示例还有另一个问题:您不能将布尔字段映射到元素文本,但是在我的真实场景中没有出现这个特定的问题……
我们经常发现自己不得不转换给我们的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();
}
}
希望这对某人有所帮助,或者至少给他们另一种选择。通常情况下,恕我直言,我更喜欢解析文件或流,但那只是我。