【问题标题】:Discrepancies in deserialization of valid xml files with System.Xml.Serialization.XmlSerializer使用 System.Xml.Serialization.XmlSerializer 反序列化有效 xml 文件的差异
【发布时间】:2010-11-14 18:59:47
【问题描述】:

一个相当复杂的问题,所以提前感谢。以下两个 xml 文件都针对给定的架构进行验证,但在尝试使用 .Net 的 XmlSerializer 进行反序列化时,只有第一个正确:

<ex:iso_10303_28 xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL" version="2.0" xmlns:ex="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common">
  <ex:iso_10303_28_header>
    <ex:name>An Example</ex:name>
    <ex:time_stamp>2010-11-12T13:04:00</ex:time_stamp>
    <ex:author>John Hancock</ex:author>
    <ex:organization>MegaCorp</ex:organization>
    <ex:preprocessor_version>a preprocessor</ex:preprocessor_version>
    <ex:originating_system>IfcXml dotNet Library</ex:originating_system>
    <ex:authorization>none</ex:authorization>
    <ex:documentation>documentation</ex:documentation>
  </ex:iso_10303_28_header>
  <ex:uos xsi:type="uos" id="uos_1" configuration="i-ifc2x3">
    <ex:Entity xsi:type="IfcOrganization" id="i1101">
      <Id xsi:nil="true" />
      <Name>MegaCorp</Name>
      <Description xsi:nil="true" />
      <Roles xsi:nil="true" />
      <Addresses xsi:nil="true" />
    </ex:Entity>
    <ex:Entity xsi:type="IfcCartesianPoint" id="i101">
      <Coordinates ex:itemType="ifc:IfcLengthMeasure" ex:cType="list">
        <IfcLengthMeasure>2500</IfcLengthMeasure>
        <IfcLengthMeasure>0</IfcLengthMeasure>
        <IfcLengthMeasure>0</IfcLengthMeasure>
      </Coordinates>
    </ex:Entity>
    <ex:Entity xsi:type="IfcDirection" id="i102">
      <DirectionRatios ex:itemType="ex:double-wrapper" ex:cType="list">
        <ex:double-wrapper>0</ex:double-wrapper>
        <ex:double-wrapper>1</ex:double-wrapper>
        <ex:double-wrapper>0</ex:double-wrapper>
      </DirectionRatios>
    </ex:Entity>
  </ex:uos>
</ex:iso_10303_28>

但是第二个文件没有正确反序列化,在下面(iso_10303_28.uos as uos1).Items被反序列化为null:

<?xml version="1.0" encoding="UTF-8"?>
<ex:iso_10303_28
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ex=
    "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common"
    xmlns="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL"
    xsi:schemaLocation="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL
    http://www.iai-tech.org/ifcXML/IFC2x3/FINAL/IFC2x3.xsd"
    version="2.0">
    <ex:iso_10303_28_header>
        <ex:name>An Example</ex:name>
        <ex:time_stamp>2010-11-12T13:04:00</ex:time_stamp>
        <ex:author>John Hancock</ex:author>
        <ex:organization>MegaCorp</ex:organization>
        <ex:preprocessor_version>a preprocessor</ex:preprocessor_version>
        <ex:originating_system>IfcXml dotNet Library</ex:originating_system>
        <ex:authorization>none</ex:authorization>
        <ex:documentation>documentation</ex:documentation>
    </ex:iso_10303_28_header>
    <uos id="uos_1" description="" configuration="i-ifc2x3" edo="">
        <IfcOrganization id="i1101">
            <Name>MegaCorp</Name>
        </IfcOrganization>
        <IfcCartesianPoint id="i101">
            <Coordinates>
                <IfcLengthMeasure>2500.0</IfcLengthMeasure>
                <IfcLengthMeasure>0.0</IfcLengthMeasure>
                <IfcLengthMeasure>0.0</IfcLengthMeasure>
            </Coordinates>
        </IfcCartesianPoint>
        <IfcDirection id="i102">
            <DirectionRatios>
                <ex:double-wrapper>0.</ex:double-wrapper>
                <ex:double-wrapper>1.</ex:double-wrapper>
                <ex:double-wrapper>0.</ex:double-wrapper>
            </DirectionRatios>
        </IfcDirection>
    </uos>
</ex:iso_10303_28>

我的反序列化器本质上是:

iso_10303_28 deserialized = (iso_10303_28)serializer.Deserialize( reader );

//using NUnit
Assert.IsNotNull(deserialized);
Assert.IsNotNull(deserialized.uos);
uos1 uos1 = deserialized.uos as uos1;
Assert.IsNotNull(uos1);
Assert.IsNotNull(uos1.Items); //<---FAILS HERE
Assert.AreEqual(3, uos1.Items.length);

uos 类是:

[System.Xml.Serialization.XmlTypeAttribute(TypeName="uos", Namespace="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")]
[System.Xml.Serialization.XmlRootAttribute("uos", Namespace="http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", IsNullable=false)]
public partial class uos1 : uos {

    private Entity[] itemsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Entity", Namespace="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")]
    public Entity[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }
}

[System.Xml.Serialization.XmlIncludeAttribute(typeof(uos1))]    
[System.Xml.Serialization.XmlTypeAttribute( Namespace="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")]
public partial class uos {

    private string idField;

    private string[] expressField;

    private string[] configurationField;

    private string[] schemaLocationField;

    private string edoField;

    private string descriptionField;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="ID")]
    public string id {
        get {
            return this.idField;
        }
        set {
            this.idField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
    public string[] express {
        get {
            return this.expressField;
        }
        set {
            this.expressField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
    public string[] configuration {
        get {
            return this.configurationField;
        }
        set {
            this.configurationField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
    public string[] schemaLocation {
        get {
            return this.schemaLocationField;
        }
        set {
            this.schemaLocationField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
    public string edo {
        get {
            return this.edoField;
        }
        set {
            this.edoField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string description {
        get {
            return this.descriptionField;
        }
        set {
            this.descriptionField = value;
        }
    }
}

iso_10303_28 的类如下:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="urn:iso.org:standard:10303:part(28):version(2):xmlschema:common", IsNullable=false)]
public partial class iso_10303_28 {

    private iso_10303_28_header iso_10303_28_headerField;

    private uos uosField;

    private string versionField;

    /// <remarks/>
    public iso_10303_28_header iso_10303_28_header {
        get {
            return this.iso_10303_28_headerField;
        }
        set {
            this.iso_10303_28_headerField = value;
        }
    }

    public enum uosChoice
    {
        [XmlEnum("http://www.iai-tech.org/ifcXML/IFC2x3/FINAL:uos")]
        uos1,
        [XmlEnum("urn:iso.org:standard:10303:part(28):version(2):xmlschema:common:uos")]
        uos
    }

    [XmlIgnore()]
    public uosChoice uosChoiceField;

    [XmlChoiceIdentifier("uosChoiceField")]
    [XmlElement(ElementName = "uos", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(uos1))]
    [XmlElement(ElementName = "uos", Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")]
    public uos uos {
        get {
            return this.uosField;
        }
        set {
            this.uosField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string version {
        get {
            return this.versionField;
        }
        set {
            this.versionField = value;
        }
    }
}

以前有人遇到过这个问题吗?是否有一个原因?我错过了什么吗?有修复或解决方法吗?

由于模式和其余代码的大小相当大,并且试图将它们简化到最小的失败部分会导致更多问题(请参阅this question),我没有将它们粘贴在这里。但是,如果需要,可以在 http://code.google.com/p/ifc-dotnet/ 找到此问题的架构、单元测试和源代码

【问题讨论】:

    标签: c# xml xml-serialization xmlserializer


    【解决方案1】:

    这两个 XML 文件不一样,在 file-1 中 uso 在 ex 下限定,所以它在 "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common " 命名空间,而在第二个不是并且在默认命名空间下。

    在 uos 类型的类 'iso_10303_28' 属性 uos 中,这意味着 XmlSerializer 将期望在与 iso_10303_28 和 'xsi:type' 'uos' 相同的命名空间下命名为 'uos' 的元素(默认情况下) 'uos' - 在同一 - “urn:iso.org:standard:10303:part(28):version(2):xmlschema:common” 命名空间下。所以这解释了为什么你在第二个 xml 中得到 null。 如果您无法控制 xml - 如果您能够反序列化其中任何一个,请尝试以下操作

    1. 类型 uos 不知道类型 uos1,除非由 XmlInclude 属性指定。我认为您还在 uos 类上添加了一个 XmlInclude 属性以将 uos1 包含为已知类型。如果不是 - 序列化程序不会反序列化第一个文件。 如果没有 - 你应该按照以下方式进行操作

      [System.Xml.Serialization.XmlInclude(typeof(uos1))] [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")] 公共部分类uos {

      }
      
    2. 您可以为属性 iso_10303_28.uos 添加 XmlElement 属性以接受任一命名空间下的名称 - 并使用选择标识符或使用“uos[]”作为类型而不是“uos”。使用选择标识符 - 它可以作为

    [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common", IsNullable = false)] 公共部分类 iso_10303_28 { 私有uos uosField;

        public enum uosChoice
        {
            [XmlEnum("http://www.iai-tech.org/ifcXML/IFC2x3/FINAL:uos")]
            uos,
            [XmlEnum("urn:iso.org:standard:10303:part(28):version(2):xmlschema:common:uos")]
            uos1
        }
    
        [XmlIgnore]
        public uosChoice uosChoiceField;
    
        [XmlChoiceIdentifier("uosChoiceField")]
        [XmlElement(ElementName = "uos", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(uos1))]
        [XmlElement(ElementName = "uos", Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")]
        public uos uos
        {
            get
            {
                return this.uosField;
            }
            set
            {
                this.uosField = value;
            }
        }
    
    
    }
    

    编辑:要正确解析项目,请像这样修改 uos1

     [System.Xml.Serialization.XmlTypeAttribute(TypeName = "uos", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")]
        [System.Xml.Serialization.XmlRootAttribute("uos", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", IsNullable = false)]
        public partial class uos1 : uos
        {
            private Entity[] itemsField;
    
            /// <remarks/>
            [XmlElement(ElementName = "Entity", Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common", Type = typeof(Entity))]
            [XmlElement(ElementName = "IfcOrganization", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(IfcOrganization))]
            [XmlElement(ElementName = "IfcCartesianPoint", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(IfcCartesianPoint))]
            [XmlElement(ElementName = "IfcDirection", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(IfcDirection))]
            public Entity[] Items
            {
                get
                {
                    return this.itemsField;
                }
                set
                {
                    this.itemsField = value;
                }
            }
    
        }
    
     [System.Xml.Serialization.XmlTypeAttribute(TypeName = "IfcOrganization", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")]
        public class IfcOrganization : Entity
        {
    
        }
    
        [System.Xml.Serialization.XmlTypeAttribute(TypeName = "IfcCartesianPoint", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")]
        public class IfcCartesianPoint : Entity
        {
    
        }
    
        [System.Xml.Serialization.XmlTypeAttribute(TypeName = "IfcDirection", Namespace = "http://www.iai-tech.org/ifcXML/IFC2x3/FINAL")]
        public class IfcDirection : Entity
        {
    
        }
    
        [XmlInclude(typeof(IfcOrganization))]
        [XmlInclude(typeof(IfcCartesianPoint))]
        [XmlInclude(typeof(IfcDirection))]
        [System.Xml.Serialization.XmlTypeAttribute(TypeName = "Entity", Namespace = "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common")]
        public class Entity
        {
    
        }
    

    【讨论】:

    • 在应用 #2 时,我遇到了一些错误。 [XmlChoiceIdentifier("ignored")] 应该是 [XmlChoiceIdentifier("uosChoice")]public uosChoice uosChoiceField 应该有 [XmlIgnore()] 属性。
    • 按照上面评论中的说明进行这些更改(作为修订版 7 提交到 code.google.com/p/ifc-dotnet/source/checkout ),反序列化测试现在反序列化 uos,所以它是不为空。不幸的是,它不能将 uos 转换为 uos1,这意味着所有重要的 uos1.Items 仍然无法访问。 :(
    • 对不起,[XmlChoiceIdentifier("ignored")] 应更改为 [XmlChoiceIdentifier("uosChoice")] 指出
    • 像这样更改 XmlElement 属性将正确解析为 uos1 [XmlElement(ElementName = "uos", Namespace = "iai-tech.org/ifcXML/IFC2x3/FINAL", Type = typeof(uos1))]
    • 我已经编辑了帖子以反映 - 在 XmlElement 中添加类型 - 它会为你工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2022-01-07
    • 2013-10-08
    • 1970-01-01
    相关资源
    最近更新 更多