<材料xmlns =“x”>不是预期的</materials>

时间:2014-05-02 07:46:37

标签: c# xml deserialization hierarchical-data xml-deserialization

我试图使用以下方法

反序列化分层xml文件
    public static T Deserialize<T>(this string serializedObj) where T : class
    {
        XmlSerializer xs = new XmlSerializer(typeof(T));
        T result;

        using (TextReader reader = new StringReader(serializedObj))
            result = xs.Deserialize(reader) as T;

        return result;
    }

但是他一直在忽视xml文件中存在对模式的引用这一事实,我不知道出了什么问题。我试图反序列化为一个对象,甚至在那里他一直在失败。

尝试反序列化xml的函数如下

    public static void RecieveAndSaveXml(string fullPath, string basePath, string fileName)
    {
        if (File.Exists(fullPath))
        {
            StreamReader reader = new StreamReader(fullPath);
            string xmlString = reader.ReadToEnd();
            Material material = xmlString.Deserialize<Material>();

            //Conversion to dataobject goes here

            reader.Close();
        }
    }

我正在尝试反序列化的课程

[Serializable]
[XmlRoot("Material")]
public class Material
{
    public Material() { }

    [XmlAttribute("MatNr")]
    public string MatNr { get; set; }
    [XmlAttribute("MatDescrEN")]
    public string MatDescrEN { get; set; }
    [XmlAttribute("MatDescrNL")]
    public string MatDescrNL { get; set; }
    [XmlAttribute("MatDescrFR")]
    public string MatDescrFR { get; set; }
    [XmlAttribute("OldMatNr")]
    public string OldMatNr { get; set; }
    [XmlAttribute("UoM")]
    public string UoM { get; set; }
    [XmlAttribute("MatGroupCode")]
    public string MatGroupCode { get; set; }
    [XmlAttribute("Extract")]
    public decimal Extract { get; set; }
    [XmlArray("AdditionalData"), XmlArrayItem(ElementName = "AddDataRecord", Type = typeof(AddDataRecord))]
    public AddDataRecord[] AdditionalData { get; set; }
    [XmlArray("PlantData"), XmlArrayItem(ElementName = "PlantDataRecord", Type = typeof(PlantDataRecord))]
    public PlantDataRecord[] PlantData { get; set; }
}

[Serializable]
[XmlRoot("AddDataRecord")]
public class AddDataRecord
{
    [XmlAttribute("UoMDenom")]
    public int UoMDenom { get; set; }
    [XmlAttribute("UoMAlt")]
    public string UoMAlt { get; set; }
    [XmlAttribute("UoMNum")]
    public int UoMNum { get; set; }
    [XmlAttribute("UoMBase")]
    public string UoMBase { get; set; }
}

[Serializable]
[XmlRoot("PlantDataRecord")]
public class PlantDataRecord
{
    [XmlAttribute("Plant")]
    public string Plant { get; set; }
    [XmlAttribute("Recipient")]
    public string Recipient { get; set; }
    [XmlAttribute("Status")]
    public string Status { get; set; }
}

}

和xml

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Materials xmlns:ns0="www.foo.be/foo/">
<Material>
    <MatNr>000000000050165478</MatNr>
    <MatDescrEN>KEG CAP GREEN PR JUP NA 1/2008</MatDescrEN>
    <MatDescrNL></MatDescrNL>
    <MatDescrFR></MatDescrFR>
    <OldMatNr>000000000000216505</OldMatNr>
    <UoM>PCE</UoM>
    <MatGroupCode>020506</MatGroupCode>
    <Extract></Extract>
    <AdditionalData>
        <AddDataRecord>
            <UoMDenom>1</UoMDenom>
            <UoMAlt>PCE</UoMAlt>
            <UoMNum>1</UoMNum>
            <UoMBase>PCE</UoMBase>
        </AddDataRecord>
    </AdditionalData>
    <PlantData>
        <PlantDataRecord>
            <Plant>BE01</Plant>
            <Recipient></Recipient>
            <Status>99</Status>
        </PlantDataRecord>
    </PlantData>
</Material>
</ns0:Materials>

所以我试过的是

  • 将嵌套类置于注释中
  • 反序列化为对象
  • 更改列表类型
  • 使用XmlArrayItem将注释从XmlAttribute更改为XmlArray
  • 添加了XmlRootItems

所以我不知道接下来会尝试什么,这就是我在这里发帖的原因。提前致谢

2 个答案:

答案 0 :(得分:1)

与提供的XML文件相比,您的类存在一些问题:

  • 示例xml中的所有属性都是elements,但C#类中有XmlAttribute
  • 您有一个不可为空的十进制值(Extract),对应的xml元素为空。如果这是一个有效的案例,你需要以某种方式处理它。
  • 您的xml表示Material的集合,但您尝试将其反序列化为Material的单个实例。

更新的代码:

[Serializable]
[XmlRoot("Material")]
public class Material
{
    public Material() { }

    [XmlElement("MatNr")]
    public string MatNr { get; set; }
    [XmlElement("MatDescrEN")]
    public string MatDescrEN { get; set; }
    [XmlElement("MatDescrNL")]
    public string MatDescrNL { get; set; }
    [XmlElement("MatDescrFR")]
    public string MatDescrFR { get; set; }
    [XmlElement("OldMatNr")]
    public string OldMatNr { get; set; }
    [XmlElement("UoM")]
    public string UoM { get; set; }
    [XmlElement("MatGroupCode")]
    public string MatGroupCode { get; set; }
    [XmlElement("Extract")]
    public String ExtractString { get; set; }
    [XmlIgnore]
    public decimal Extract
    {
        get { return String.IsNullOrWhiteSpace(this.ExtractString) ? 0M : decimal.Parse(this.ExtractString); }
        set { this.ExtractString = this.Extract.ToString(CultureInfo.InvariantCulture); }
    }
    [XmlArray("AdditionalData"), XmlArrayItem(ElementName = "AddDataRecord", Type = typeof(AddDataRecord))]
    public AddDataRecord[] AdditionalData { get; set; }
    [XmlArray("PlantData"), XmlArrayItem(ElementName = "PlantDataRecord", Type = typeof(PlantDataRecord))]
    public PlantDataRecord[] PlantData { get; set; }
}

[Serializable]
[XmlRoot("AddDataRecord")]
public class AddDataRecord
{
    [XmlElement("UoMDenom")]
    public int UoMDenom { get; set; }
    [XmlElement("UoMAlt")]
    public string UoMAlt { get; set; }
    [XmlElement("UoMNum")]
    public int UoMNum { get; set; }
    [XmlElement("UoMBase")]
    public string UoMBase { get; set; }
}

[Serializable]
[XmlRoot("PlantDataRecord")]
public class PlantDataRecord
{
    [XmlElement("Plant")]
    public string Plant { get; set; }
    [XmlElement("Recipient")]
    public string Recipient { get; set; }
    [XmlElement("Status")]
    public string Status { get; set; }
}

[XmlRoot("Materials", Namespace = "www.foo.be/foo/")]
[Serializable]
public class MaterialCollection
{
   [XmlElement("Material", Namespace="")]
   public List<Material> Materials { get; set; }
}

然后你需要使用

MaterialCollection materials = xmlString.Deserialize<MaterialCollection>();

答案 1 :(得分:1)

手动编写类的替代方法是使用xsd.exe工具生成类文件。

Visual Studio的最新版本不再包含它,所以你必须得到here

假设您的xml文件位于c:\下,您可以从那里调用xsd.exe,您可以按以下方式生成materials.cs文件:

c:\>xsd materials.xml

接着是

c:\>xsd materials.xsd /classes