【问题标题】:Deserializing XML attribute 'xsi:type'反序列化 XML 属性“xsi:type”
【发布时间】:2015-10-24 16:35:20
【问题描述】:

这是我第一次在 stackoverflow 上提问,也是第一次使用 xml 文件,所以我认为不会比这更糟了。 我需要反序列化一些长 XML,但困扰我的部分如下:

<CastleConfigSub xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../xsd/c5c.xsd" Format="1">
  <ConfigFile Name="EdgeDetection">
    <Interfaces>
      <Interface Name="EdgeDetectionModule">
        <Doc />
         <Functions>
          <Function Name="MonitorNoChanges">
            <Doc>This Function checks that no edge has been detected at the specified                    digital channel for a specific time in msec
            	1. DigitalChanelToWatch: This is the digital Input channel to monitor                      edges on it.
            	2. TimeOut: This is the monitoring Period for the edges on the digitial                    input channel.
            </Doc>
            <Args>
              <Arg xsi:type="ArgEnum" Name="DigitalChanelToWatch"                                      Enum="DigitalInChannelID" />
              <Arg xsi:type="ArgValue" Name="TimeOut" EncodedType="uint32"                               Unit="msec" />
            </Args>
           </Function>
          </Functions>
        </Interface>
      </Interfaces>
    </ConfigFile>
  </CastleConfigSub>
public class CastleConfigSub
{
    [XmlElement("Options")]
    public Options options = new Options();

    [XmlElement("ConfigFile")]
    public ConfigFile configFile= new ConfigFile();


} 
public class ConfigFile
{
    [XmlElement("Doc")]
    public string doc {get; set;} 
    [XmlElement("History")]
    public History history = new History();
    [XmlElement("Includes")]
    public Includes includes = new Includes();
    [XmlElement("Options")]
    public Options options = new Options();
    [XmlElement("DataTypes")]
    public DataTypes dataTypes = new DataTypes();

    [XmlArray("Interfaces")]
    [XmlArrayItem("Interface")]
    public List<Interface> interfaces = new List<Interface>();


}
 public class Interface
{
    [XmlAttribute("Name")]
    public string name="";
    [XmlElement("Doc")]
    [XmlArray("Functions")]
    [XmlArrayItem("Function")]
    public List<Function> functions = new List<Function>();
}
public class Function
{

    [XmlAttribute("Name")]
    public string name="";
    [XmlElement("Doc")]
    public string doc="";
    [XmlArray("Args")]
    [XmlArrayItem("Arg")]
    public List<Arg> args = new List<Arg>();
}
public class Arg
{
    [XmlAttribute ("xsi:type")]
    public string type = "";
    [XmlAttribute("Name")]
    public string name ="";
    [XmlAttribute("EncodedType")]
    public string encodedType="";
    [XmlAttribute("Enum")]
    public string enumName ="";
    [XmlAttribute("Unit")]
    public string unit="";

}

我知道一切都很混乱,但我不能做得更好:/。

【问题讨论】:

  • 您的具体问题是什么?您可能希望使用 .net 框架提供的工具 XSD.exe 从 XML 文件 (msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.110).aspx) 生成 C# 类。
  • 你真的需要“接口”和“接口”吗? “功能”和“功能”呢?和“args”和“arg”。将 XmlArrayItem 更改为 XmlElement 会删除这些重复的标签。
  • @jdweng 是的,我确实需要它们,因为这不是完整的 xml 文件,完整的 xml 文件有很多接口、函数和参数,所以我想我需要这种方式。
  • @PhillipH 我的问题是此代码导致“出现错误反映类型异常”
  • 类型异常通常发生在字符串不会转换为数字时。您仍然可以拥有没有双标签(Args、Arg)的数组。不需要 Args 标签。只需删除 Args(连同 XmlArray)并使 Arg 成为 XmlElement(不是 XmlArray)。

标签: c# xml serialization deserialization


【解决方案1】:

上一个答案很好,帮助我解决了我的问题,但是我有额外的工作来处理 xml 元素中的不同命名空间及其属性值,所以我的解决方案在这里:

有以下xml

<?xml version="1.0" encoding="utf-16"?>
<RootType xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://my.custom.namespace.com">
  <description>some description</description>
  <values>
    <field>some field</field>
    <value xsi:type="xsd:double">1000.00</value>
  </values>
</RootType>

反序列化的对象集如下

[XmlRoot(ElementName = "RootType", Namespace = "http://my.custom.namespace.com")]
public sealed class Root
{
    [XmlElement("description")]
    public string Description { get; set; }

    [XmlElement("values")]
    public Value[] Values { get; set; }
}

public sealed class Value
{
    [XmlElement("field")]
    public string Field { get; set; }

    [XmlElement("value", IsNullable = true)]
    public ValueProperty ValueProperty { get; set; }
}

[XmlInclude(typeof(CustomDouble))]
[XmlRoot(Namespace = "http://my.custom.namespace.com")]
public class ValueProperty
{
    [XmlText]
    public string Value { get; set; }
}

[XmlType(TypeName = "double", Namespace = "http://www.w3.org/2001/XMLSchema")]
public class CustomDouble : ValueProperty
{
}

【讨论】:

    【解决方案2】:

    请试试这个:

    public class CastleConfigSub
    {
        public ConfigFile ConfigFile { get; set; }
        [XmlAttribute()]
        public byte Format { get; set; }
    }
    public class ConfigFile
    {
        public List<Interface> Interfaces { get; set; }
        [XmlAttribute()]
        public string Name { get; set; }
    }
    public class Interface
    {
        public object Doc { get; set; }
        public List<Function> Functions { get; set; }
        [XmlAttribute()]
        public string Name { get; set; }
    }
    public class Function
    {
        public string Doc { get; set; }
        [XmlArrayItem("Arg")]
        public List<Arg> Args { get; set; }
        [XmlAttribute()]
        public string Name { get; set; }
    }
    [XmlInclude(typeof(ArgEnum))]
    [XmlInclude(typeof(ArgValue))]
    public class Arg
    {
        [XmlAttribute()]
        public string Name { get; set; }
    }
    public class ArgEnum : Arg
    {
        [XmlAttribute()]
        public string Enum { get; set; }
    }
    public class ArgValue : Arg
    {
        [XmlAttribute()]
        public string EncodedType { get; set; }
        [XmlAttribute()]
        public string Unit { get; set; }
    }
    

    我不知道接口和功能元素存在多少次。所以我做了 List 集合。

    【讨论】:

    • 效果很好。如果你能解释一下为什么必须这样?'xsi:type'是一个关键字还是一个特殊的属性,我不能像其他的一样得到?
    • XmlSerializer 类使用xsi:type 属性来确定从包含该属性的 XML 实例元素中反序列化的对象类型。该类型必须存在于派生层次结构中。 (前缀 xsi 用于 XML Schema 实例命名空间 w3.org/2001/XMLSchema-instance,适用于旨在符合指定 XML 模式的 XML 实例文档。)另外,请参阅 here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    相关资源
    最近更新 更多