.NET XML反序列化用于具有不同值的字段

时间:2016-02-02 14:37:04

标签: c# xml xml-parsing

我有以下XML:

<results>
<row>
    <id>4990321</id>
    <field name="First name">John</field>
    <field name="Last name">Snow</field>
    <field name="Country">USA</field>
    <field name="City">San-Diego</field>
    <field name="Postcode">123456</field>
    <field name="Email">username@stackoverflow.com</field>
    <field name="Message">Hello</field>
</row>
<row>
    ...
<row>
</results>

我需要在对象数组中反序列化它:

public class Employee
{
    public string Id { set; get; }
    public string Firstname { set; get; }
    public string Lastname { set; get; }
    public string Country { set; get; }
    public string City { set; get; }
    public string Postcode { set; get; }
    public string Email { set; get; }
    public string Message { set; get; }
}

我尝试使用XmlElementAttributeXmlAttributeAttribute来实现它,但是名为ElementName的属性不理解XPath,因此无法获取特定字段的值(如{ {1}})

谁有任何想法我该怎么办?没有XDocument解析的理想选择。

2 个答案:

答案 0 :(得分:1)

一个建议是将数据预处理为通过XSLT转换更友好地序列化的表单。这可以通过XslCompiledTransform类在C#中完成。

要使用的示例XSL文件是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="UTF-8" indent="yes" method="xml" standalone="no" omit-xml-declaration="no"/>
    <xsl:template match="results">
        <Employees>
        <xsl:for-each select="row">
            <Employee>
                 <Id><xsl:value-of select="id" /></Id>
                 <Firstname><xsl:value-of select="field[@name='First name']" /></Firstname>
                 <Lastname><xsl:value-of select="field[@name='Last name']" /></Lastname>
                 <Country><xsl:value-of select="field[@name='Country']" /></Country>
            </Employee>
        </xsl:for-each>
        </Employees>
    </xsl:template>
</xsl:stylesheet>

(不完整但足以用于说明目的)

在您的C#程序中,转换很简单:

var xslReader = XmlReader.Create(new StringReader(GetXslString()));
var xmlReader = XmlReader.Create(new StringReader(GetXmlString()));

var transformedStream = new MemoryStream();

var xmlWriter = XmlWriter.Create(transformedStream);
var xslt = new XslCompiledTransform();

xslt.Load(xslReader);
xslt.Transform(xmlReader, xmlWriter);

transformedStream.Seek(0, SeekOrigin.Begin);

// Use your transformedStream to deserialize the object

.NET小提示演示此代码here

当针对您的样本数据运行时,它会生成类似于:

的输出
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Employees>
    <Employee>
        <Id>4990321</Id>
        <Firstname>Jhon</Firstname>
        <Lastname>Snow</Lastname>
        <Country>USA</Country>
    </Employee>
    <Employee>
        <Id>4990322</Id>
        <Firstname>Mike</Firstname>
        <Lastname>Ross</Lastname>
        <Country>UK</Country>
    </Employee>
</Employees>

现在,任何默认的反序列化工具都可以在没有高级文档选择器等的情况下接管,这应该相当容易。

答案 1 :(得分:0)

您可以通过使用let saf_sub=substitute(saf_data, "@@newline@@", "\r","g") 显式声明元素反序列化的顺序来反序列化它:

Order

然后您可以将其反序列化(其中[XmlRoot("results")] public class Results { [XmlElement("row")] public List<Employee> Employees { get; set; } } public class Employee { [XmlElement(ElementName = "id", Order = 1)] public string Id { set; get; } [XmlElement(ElementName = "field", Order = 2)] public string Firstname { set; get; } [XmlElement(ElementName = "field", Order = 3)] public string Lastname { set; get; } [XmlElement(ElementName = "field", Order = 4)] public string Country { set; get; } [XmlElement(ElementName = "field", Order = 5)] public string City { set; get; } [XmlElement(ElementName = "field", Order = 6)] public string Postcode { set; get; } [XmlElement(ElementName = "field", Order = 7)] public string Email { set; get; } [XmlElement(ElementName = "field", Order = 8)] public string Message { set; get; } } 是您的XML字符串):

xml