【问题标题】:When do you have to specify the root node to deserialize xml?什么时候必须指定根节点来反序列化xml?
【发布时间】:2018-05-03 15:26:22
【问题描述】:

我正在尝试反序列化来自 Web API 服务的 xml。仅当我使用指定根节点名称和命名空间的根节点 XmlRootAttribute 类型实例化 XmlSerializer 对象时,它才有效。如果它是只有一个根节点的正确 xml,为什么我需要告诉它根的名称?我看到人们不这样做的例子。我希望尽可能保持通用性。

这是反序列化的代码。我希望注释掉的行在我没有指定根节点的情况下工作,但它在底部给出了错误。

public static T xmlToObject<T>(string strXML)
        {
            XmlRootAttribute xRoot = new XmlRootAttribute();
            xRoot.ElementName = "QIMonthReturn";
            xRoot.Namespace = "QI.Measures.API";

            XmlSerializer serializer = new XmlSerializer(typeof(T), xRoot);
            //XmlSerializer serializer = new XmlSerializer(typeof(T)); 

            StringReader rdr = new StringReader(strXML);

            return (T)serializer.Deserialize(rdr);
        }

错误(我去掉了尖括号):

{"There is an error in XML document (2, 2)."}
{"QIMonthReturn xmlns='QI.Measures.API' was not expected."}

类:

public class QIMonth
{
    [XmlElement(ElementName = "Date", DataType = "dateTime")]
    public DateTime Date { get; set; }

    [XmlElement(ElementName = "Numerator", DataType = "boolean")]
    public bool Numerator { get; set; }

    [XmlElement(ElementName = "Denominator", DataType = "boolean")]
    public bool Denominator { get; set; }
}   

[XmlRoot("QIMonthReturn")]
public class QIMonthReturn
{
    public QIMonthReturn()
    {         
        Months = new List<QIMonth>();
    }

    [XmlElement(ElementName = "PatientKey")]
    public string PatientKey { get; set; }

    [XmlArray("Months"), XmlArrayItem("QIMonth")]  
    public List<QIMonth> Months { get; set; }
}

我确实在 QIMonth 上面有 XmlRoot 属性,但取出来了,不知道是否需要。

我在哪里添加命名空间:

public static void Register(HttpConfiguration config)
    {           
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.Formatters.Clear();
        config.Formatters.Add(new CustomNamespaceXmlFormatter("QI.Measures.API") { UseXmlSerializer = true });
    }

【问题讨论】:

  • 向我们展示您的 C# 类模型定义。

标签: c# xml


【解决方案1】:

如果您将命名空间添加到您的模型类,您的代码将可以工作。在你的问题中,你已经编辑了命名空间,所以我编了一个。

<?xml version="1.0" ?>
<QIMonthReturn xmlns="SomeNamespaceHere">
    <PatientKey>25</PatientKey>
    <Months>
        <QIMonth>
            <Date>2018-05-03T11:13:02.1312881-04:00</Date>
            <Numerator>false</Numerator>
            <Denominator>true</Denominator>
        </QIMonth>
    </Months>
</QIMonthReturn>


[XmlRoot("QIMonthReturn", Namespace="SomeNamespaceHere")]
public class QIMonthReturn
{
    public QIMonthReturn()
    {
        Months = new List<QIMonth>();
    }

    [XmlElement(ElementName = "PatientKey")]
    public string PatientKey { get; set; }

    [XmlArray("Months"), XmlArrayItem("QIMonth")]
    public List<QIMonth> Months { get; set; }
}

public static T xmlToObject<T>(string strXML)
{
    XmlSerializer serializer = new XmlSerializer(typeof(T));

    StringReader rdr = new StringReader(strXML);

    return (T)serializer.Deserialize(rdr);
}

引用 Marc 的answer

【讨论】:

  • 我忘了提到我在 WebApiConfig 类的另一个地方添加了命名空间,因为我添加了一个自定义类来进行 XML 格式化,因此它不会添加 Web API 自动添加的两个命名空间。我也会补充一下(我担心我的问题会变得非常臃肿)
  • 我没有看到您是如何将命名空间添加到 XmlRoot 属性的——现在我这样做了,我可以在反序列化时不指定命名空间来运行它(而且我仍然只有一个命名空间! )。甜
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2014-02-03
  • 1970-01-01
  • 1970-01-01
  • 2014-11-08
相关资源
最近更新 更多