繁体   English   中英

c# xml 反序列化为 xsi:type 值中带有冒号和连字符的对象

[英]c# xml deserialization to object with colon and hyphen in xsi:type value

当我尝试使用XmlSerializer类将 XML 文件反序列化为对象时遇到问题。

我的 XML 文件如下所示:

<fx:FIBEX xmlns:fx="http://www.asam.net/xml/fbx" xmlns:ho="http://www.asam.net/xml" xmlns:ethernet="http://www.asam.net/xml/fbx/ethernet" xmlns:it="http://www.asam.net/xml/fbx/it" xmlns:service="http://www.asam.net/xml/fbx/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="" VERSION="4.1.0">
  <fx:ELEMENTS>
    <fx:CLUSTERS>
      <fx:CLUSTER xsi:type="ethernet:CLUSTER-TYPE" ID="ID_CLUSTER_MAIN_1">
        <ho:SHORT-NAME>SomeIpDatabase</ho:SHORT-NAME>
        <fx:SPEED>1000000000</fx:SPEED>
        <fx:IS-HIGH-LOW-BIT-ORDER>false</fx:IS-HIGH-LOW-BIT-ORDER>
        <fx:BIT-COUNTING-POLICY>SAWTOOTH</fx:BIT-COUNTING-POLICY>
        <fx:PROTOCOL>ETHERNET</fx:PROTOCOL>
        <fx:PHYSICAL>OABR</fx:PHYSICAL>
        <fx:CHANNEL-REFS>
          <fx:CHANNEL-REF ID-REF="ID_CHANNEL_SOME_IP_1" />
        </fx:CHANNEL-REFS>
        <fx:MAX-FRAME-LENGTH>1500</fx:MAX-FRAME-LENGTH>
        <ethernet:MAC-MULTICAST-GROUPS>
          <ethernet:MAC-MULTICAST-GROUP ID="ID_CLUSTER_MAIN_1_ID_MACMULTICASTGROUP_SD_1">
            <ho:SHORT-NAME>SD</ho:SHORT-NAME>
            <ethernet:MAC-MULTICAST-ADDRESS>01:00:5E:40:FF:FB</ethernet:MAC-MULTICAST-ADDRESS>
          </ethernet:MAC-MULTICAST-GROUP>
          <ethernet:MAC-MULTICAST-GROUP ID="ID_CLUSTER_MAIN_1_ID_MACMULTICASTGROUP_BROADCAST_1">
            <ho:SHORT-NAME>BROADCAST</ho:SHORT-NAME>
            <ethernet:MAC-MULTICAST-ADDRESS>FF:FF:FF:FF:FF:FF</ethernet:MAC-MULTICAST-ADDRESS>
          </ethernet:MAC-MULTICAST-GROUP>
        </ethernet:MAC-MULTICAST-GROUPS>
      </fx:CLUSTER>
      <!--Additional CLUSTER elements omitted-->
    </fx:CLUSTERS>
  </fx:ELEMENTS>
  <!--PROJECT elements omitted-->
</fx:FIBEX>

当我现在尝试反序列化 XML 文件时,我收到以下错误:

System.InvalidOperationException: Error in XML-Dokument (11,5). ---> System.InvalidOperationException: The specified type was not recognized: Name='CLUSTER-TYPE', Namespace='http://www.asam.net/xml/fbx/ethernet', at <CLUSTER xmlns='http://www.asam.net/xml/fbx'>.

我的解串器类如下所示:

public static T DeserializeXMLFileToObject<T>(string XmlFilename)
{
    T returnObject = default(T);
    if (string.IsNullOrEmpty(XmlFilename)) return default(T);

    try
    {
        StreamReader xmlStream = new StreamReader(XmlFilename);
        XmlSerializer serializer = new XmlSerializer(typeof(T));
        returnObject = (T)serializer.Deserialize(xmlStream);
    }
    catch (Exception ex)
    {
        Console.Write("{1} Es ist ein Fehler aufgetreten {0}", ex, DateTime.Now);
    }
    return returnObject;
}

应包含 XML 文件的反序列​​化元素和属性的类如下所示:

[XmlRoot("FIBEX", Namespace = fxNameSpace)]
public class Fibextoobject
{
    [XmlElement("PROJECT", Namespace = fxNameSpace)]
    public Project project { get; set; }

    [XmlElement("ELEMENTS", Namespace = fxNameSpace)]
    public Elements elements { get; set; }

    public class Project
    {
        [XmlAttribute("OID", Namespace = hoNameSpace)]
        public string OID { get; set; }

        [XmlAttribute("ID")]
        public string ID { get; set; }

        [XmlElement("SHORT-NAME", Namespace = hoNameSpace)]
        public string shortname { get; set; }

        [XmlElement("LONG-NAME", Namespace = hoNameSpace)]
        public string longname { get; set; }
    }

    public class Elements
    {
        [XmlArray("CLUSTERS", Namespace = fxNameSpace)]
        [XmlArrayItem("CLUSTER", Namespace = fxNameSpace)]
        public List<Cluster> cluster { get; set; }

    }

    public class Cluster
    {
        [XmlAttribute("ID")]
        public string ID { get; set; }

        [XmlElement("SHORT-NAME", Namespace = hoNameSpace)]
        public string shortname { get; set; }

        [XmlElement("SPEED", Namespace = fxNameSpace)]
        public string speed { get; set; }
    }
}

如何使用 xsi:type 属性和值中的冒号和连字符成功反序列化 XML 文件: xsi:type="ethernet:CLUSTER-TYPE"

你的问题如下。 xsi:type属性是{http://www.w3.org/2001/XMLSchema-instance}type缩写,是一个w3c 标准属性,它允许元素显式声明其类型,例如,当它是预期的元素类型。 XmlSerializer支持此属性,并将使用它来确定要为此类多态类型反序列化的对象的实际类型。 但是,使用此属性有几个注意事项和限制:

  1. 如果xsi:type存在于 XML 中,则该元素必须绑定到多态类型层次结构。 XmlSerializer永远不会忽略该属性。 因此,您需要引入Cluster的派生子类型来反序列化此 XML,例如:

     public class ClusterType : Cluster { }
  2. XmlSerializer要求使用[XmlInclude(typeof(TDerivedType))]提前通知所有可能的子类型。 通常人们会将此属性放在基本类型上:

     [XmlInclude(typeof(ClusterType))] // Add XmlInclude for all additional subtypes here. public class Cluster { // Remainder unchanged
  3. 您的xsi:type值包含无法包含在 ac# 标识符中的字符:

     xsi:type="ethernet:CLUSTER-TYPE"

    在这种情况下, XmlSerializer将该值解释为限定名称,其中:之前的部分是作用域中有效命名空间的 XML 命名空间前缀,后面的部分对应于多态类型的XmlTypeAttribute.TypeName 您可以通过将[XmlType]属性应用于派生类型来通知序列化程序预期的命名空间和类型,如下所示:

     [XmlType("CLUSTER-TYPE", Namespace = ethernetNameSpace)] public class ClusterType : Cluster { }

    其中ethernetNameSpace定义为:

     public const string ethernetNameSpace = "http://www.asam.net/xml/fbx/ethernet";
  4. 出于某种原因,如果XmlSerializer在包含的派生类型上设置为任何内容,XmlSerializer需要将XmlTypeAttribute.Namespace初始化为基类型上的内容 在反序列化派生类型的实例时,命名空间的值似乎并不重要(尽管在反序列化基类型时很明显),它只需要设置为something 即使是空字符串也能工作,例如:

     // The XmlTypeAttribute.Namespace below must be initialized to something if it is also initialized on the derived type. // However, the actual value does not need to be the same as the child's namespace, so modify to be something more appropriate // based on additional XML samples. [XmlType("CLUSTER", Namespace = "")] [XmlInclude(typeof(ClusterType))] // Add XmlInclude for all additional subtypes here. public class Cluster { // Remainder unchanged

    如果未设置基本类型 XML 命名空间, XmlSerializer将抛出带有误导性消息的异常:

    System.InvalidOperationException: 生成 XML 文档时出错。 ---> System.InvalidOperationException: Fibextoobject+ClusterType 类型不是预期的。 使用 XmlInclude 或 SoapInclude 属性指定静态未知的类型。

    由于ClusterType实际上是通过[XmlInclude]包含的,因此该消息没有帮助。 需要进行一些实验才能确定实际问题。

将上述所有项目付诸实施的Fibextoobject类型的工作版本如下:

[XmlRoot("FIBEX", Namespace = fxNameSpace)]
public partial class Fibextoobject
{
    [XmlElement("PROJECT", Namespace = fxNameSpace)]
    public Project project { get; set; }

    [XmlElement("ELEMENTS", Namespace = fxNameSpace)]
    public Elements elements { get; set; }

    public class Project
    {
        [XmlAttribute("OID", Namespace = hoNameSpace)]
        public string OID { get; set; }

        [XmlAttribute("ID")]
        public string ID { get; set; }

        [XmlElement("SHORT-NAME", Namespace = hoNameSpace)]
        public string shortname { get; set; }

        [XmlElement("LONG-NAME", Namespace = hoNameSpace)]
        public string longname { get; set; }
    }

    public class Elements
    {
        [XmlArray("CLUSTERS", Namespace = fxNameSpace)]
        [XmlArrayItem("CLUSTER", Namespace = fxNameSpace)]
        public List<Cluster> cluster { get; set; }
    }

    [XmlType("CLUSTER-TYPE", Namespace = ethernetNameSpace)]
    public class ClusterType : Cluster
    {
    }

    // The XmlTypeAttribute.Namespace below must be initialized to something if it is also initialized on the derived type.
    // However, the actual value does not need to be the same as the child's namespace, so modify to be something more appropriate
    // based on additional XML samples.
    [XmlType("CLUSTER", Namespace = "")] 
    [XmlInclude(typeof(ClusterType))]
    // Add XmlInclude for all additional subtypes here.
    public class Cluster
    {
        [XmlAttribute("ID")]
        public string ID { get; set; }

        [XmlElement("SHORT-NAME", Namespace = hoNameSpace)]
        public string shortname { get; set; }

        [XmlElement("SPEED", Namespace = fxNameSpace)]
        public string speed { get; set; }
    }
}

public partial class Fibextoobject
{
    public const string fxNameSpace = "http://www.asam.net/xml/fbx";
    public const string hoNameSpace = "http://www.asam.net/xml";
    public const string ethernetNameSpace = "http://www.asam.net/xml/fbx/ethernet";
    public const string itNameSpace = "http://www.asam.net/xml/fbx/it";
    public const string serviceNameSpace = "http://www.asam.net/xml/fbx/services";
}

示例工作Roslyn .Net fiddle

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM