使用 System.Xml.Serialization.XmlSerializer 反序列化有效 xml 文件的差异 [英] Discrepancies in deserialization of valid xml files with System.Xml.Serialization.XmlSerializer

查看:24
本文介绍了使用 System.Xml.Serialization.XmlSerializer 反序列化有效 xml 文件的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

A fairly involved question, so thanks in advance. The following two xml files both validate against the given schemas, but on attempting to deserialize using .Net's XmlSerializer only the first does so correctly:

<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 反序列化为空:

but the second file does not deserialize correctly, in the below (iso_10303_28.uos as uos1).Items is deserialized as 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;
        }
    }
}

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

Has anyone come across this issue before? Is there a reason for this? Have I missed something? is there a fix or workaround?

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

As the schemas and rest of the code is fairly large in size, and trying to simplify them down to the minimum failing part caused more problems (see this question) I've not pasted them here. However, if required, schemas, unit tests and source for this issue can be found at http://code.google.com/p/ifc-dotnet/

推荐答案

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

The two XML files aren't the same, in file-1 uso is qualified under ex so it is under "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common" namespace, while in second it is not and is under default namespace.

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

In class 'iso_10303_28' property uos of type uos which means that XmlSerializer will expect elements with name 'uos' (by default) under the same namespace as that of iso_10303_28 and 'xsi:type' 'uos' as described by class 'uos'- under the same - "urn:iso.org:standard:10303:part(28):version(2):xmlschema:common" namespace. So this explains why you get null in second xml. If you have no control over xml - and should you be able to deserialize either of them, try following

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

  1. Type uos has no knowledge of type uos1 unless specified by XmlInclude attribute. I think what you've additionally added an XmlInclude attribute on uos class to include uos1 as a known type. If not - the serializer won't de-serialize first file. If not - you should do that as below

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

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

}

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

  • You can add XmlElement attributes for property iso_10303_28.uos to accept names under either namespace - and use a choice identifier or use 'uos[]' as type instead of 'uos'. With choice identifier - it can be done as

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

    [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 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

    To parse Items correctly, modify uos1 like this

     [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
        {
    
        }
    

    这篇关于使用 System.Xml.Serialization.XmlSerializer 反序列化有效 xml 文件的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆