Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “的正确XML序列化和反序列化”;混合;NET中的类型_C#_.net_Xml Serialization - Fatal编程技术网

C# “的正确XML序列化和反序列化”;混合;NET中的类型

C# “的正确XML序列化和反序列化”;混合;NET中的类型,c#,.net,xml-serialization,C#,.net,Xml Serialization,我当前的任务是编写一个类库来处理HL7 CDA文件。 这些HL7CDA文件是具有已定义XML模式的XML文件,因此我使用xsd.exe生成.NET类以进行XML序列化和反序列化 XML架构包含各种类型,其中包含mixed=“true”属性,指定此类型的XML节点可能包含与其他XML节点混合的普通文本。 其中一种类型的XML模式的相关部分如下所示: <xs:complexType name="StrucDoc.Paragraph" mixed="true"> <xs:se

我当前的任务是编写一个类库来处理HL7 CDA文件。
这些HL7CDA文件是具有已定义XML模式的XML文件,因此我使用xsd.exe生成.NET类以进行XML序列化和反序列化

XML架构包含各种类型,其中包含mixed=“true”属性,指定此类型的XML节点可能包含与其他XML节点混合的普通文本。
其中一种类型的XML模式的相关部分如下所示:

<xs:complexType name="StrucDoc.Paragraph" mixed="true">
    <xs:sequence>
        <xs:element name="caption" type="StrucDoc.Caption" minOccurs="0"/>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="br" type="StrucDoc.Br"/>
            <xs:element name="sub" type="StrucDoc.Sub"/>
            <xs:element name="sup" type="StrucDoc.Sup"/>
            <!-- ...other possible nodes... -->
        </xs:choice>
    </xs:sequence>
    <xs:attribute name="ID" type="xs:ID"/>
    <!-- ...other attributes... -->
</xs:complexType>
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(TypeName="StrucDoc.Paragraph", Namespace="urn:hl7-org:v3")]
public partial class StrucDocParagraph {

    private StrucDocCaption captionField;

    private object[] itemsField;

    private string[] textField;

    private string idField;

    // ...fields for other attributes...

    /// <remarks/>
    public StrucDocCaption caption {
        get {
            return this.captionField;
        }
        set {
            this.captionField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("br", typeof(StrucDocBr))]
    [System.Xml.Serialization.XmlElementAttribute("sub", typeof(StrucDocSub))]
    [System.Xml.Serialization.XmlElementAttribute("sup", typeof(StrucDocSup))]
    // ...other possible nodes...
    public object[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    public string[] Text {
        get {
            return this.textField;
        }
        set {
            this.textField = value;
        }
    }

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

    // ...properties for other attributes...
}
<paragraph>first line<br /><br />third line</paragraph>
itemsField = new object[]
{
    new StrucDocBr(),
    new StrucDocBr(),
};
textField = new string[]
{
    "first line",
    "third line",
};
<paragraph>
    <br />
    <br />first linethird line
</paragraph>
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(TypeName="StrucDoc.Paragraph", Namespace="urn:hl7-org:v3")]
public partial class StrucDocParagraph {

    private StrucDocCaption captionField;

    private object[] itemsField;

    private string idField;

    // ...fields for other attributes...

    /// <remarks/>
    public StrucDocCaption caption {
        get {
            return this.captionField;
        }
        set {
            this.captionField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("br", typeof(StrucDocBr))]
    [System.Xml.Serialization.XmlElementAttribute("sub", typeof(StrucDocSub))]
    [System.Xml.Serialization.XmlElementAttribute("sup", typeof(StrucDocSup))]
    // ...other possible nodes...
    [System.Xml.Serialization.XmlTextAttribute(typeof(string))]
    public object[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }

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

    // ...properties for other attributes...
}
<paragraph>first line<br /><br />third line</paragraph>
itemsField = new object[]
{
    "first line",
    new StrucDocBr(),
    new StrucDocBr(),
    "third line",
};
因此,无法确定文本和其他节点的确切顺序。
如果我再次序列化
,结果如下所示:

<xs:complexType name="StrucDoc.Paragraph" mixed="true">
    <xs:sequence>
        <xs:element name="caption" type="StrucDoc.Caption" minOccurs="0"/>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="br" type="StrucDoc.Br"/>
            <xs:element name="sub" type="StrucDoc.Sub"/>
            <xs:element name="sup" type="StrucDoc.Sup"/>
            <!-- ...other possible nodes... -->
        </xs:choice>
    </xs:sequence>
    <xs:attribute name="ID" type="xs:ID"/>
    <!-- ...other attributes... -->
</xs:complexType>
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(TypeName="StrucDoc.Paragraph", Namespace="urn:hl7-org:v3")]
public partial class StrucDocParagraph {

    private StrucDocCaption captionField;

    private object[] itemsField;

    private string[] textField;

    private string idField;

    // ...fields for other attributes...

    /// <remarks/>
    public StrucDocCaption caption {
        get {
            return this.captionField;
        }
        set {
            this.captionField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("br", typeof(StrucDocBr))]
    [System.Xml.Serialization.XmlElementAttribute("sub", typeof(StrucDocSub))]
    [System.Xml.Serialization.XmlElementAttribute("sup", typeof(StrucDocSup))]
    // ...other possible nodes...
    public object[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    public string[] Text {
        get {
            return this.textField;
        }
        set {
            this.textField = value;
        }
    }

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

    // ...properties for other attributes...
}
<paragraph>first line<br /><br />third line</paragraph>
itemsField = new object[]
{
    new StrucDocBr(),
    new StrucDocBr(),
};
textField = new string[]
{
    "first line",
    "third line",
};
<paragraph>
    <br />
    <br />first linethird line
</paragraph>
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(TypeName="StrucDoc.Paragraph", Namespace="urn:hl7-org:v3")]
public partial class StrucDocParagraph {

    private StrucDocCaption captionField;

    private object[] itemsField;

    private string idField;

    // ...fields for other attributes...

    /// <remarks/>
    public StrucDocCaption caption {
        get {
            return this.captionField;
        }
        set {
            this.captionField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("br", typeof(StrucDocBr))]
    [System.Xml.Serialization.XmlElementAttribute("sub", typeof(StrucDocSub))]
    [System.Xml.Serialization.XmlElementAttribute("sup", typeof(StrucDocSup))]
    // ...other possible nodes...
    [System.Xml.Serialization.XmlTextAttribute(typeof(string))]
    public object[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }

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

    // ...properties for other attributes...
}
<paragraph>first line<br /><br />third line</paragraph>
itemsField = new object[]
{
    "first line",
    new StrucDocBr(),
    new StrucDocBr(),
    "third line",
};



第一行第三行
默认序列化程序只是先序列化项,然后序列化文本

我尝试在StrucDocParague类上实现
IXmlSerializable
,以便控制内容的反序列化和序列化,但这相当复杂,因为涉及到太多类,我还没有找到解决方案,因为我不知道这项工作是否有回报

对于这个问题是否有某种简单的解决方法,或者甚至可以通过
IXmlSerializable
进行自定义序列化? 或者我应该使用
XmlDocument
XmlReader
/
XmlWriter
来处理这些文档吗?

怎么办

itemsField = new object[] 
{ 
    "first line", 
    new StrucDocBr(), 
    new StrucDocBr(), 
    "third line", 
};

为了解决这个问题,我必须修改生成的类:

  • XmlTextAttribute
    Text
    属性移动到
    Items
    属性,并添加参数
    Type=typeof(string)
  • 删除
    文本
    属性
  • 删除
    textField
    字段
  • 因此,生成的代码(已修改)如下所示:

    <xs:complexType name="StrucDoc.Paragraph" mixed="true">
        <xs:sequence>
            <xs:element name="caption" type="StrucDoc.Caption" minOccurs="0"/>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="br" type="StrucDoc.Br"/>
                <xs:element name="sub" type="StrucDoc.Sub"/>
                <xs:element name="sup" type="StrucDoc.Sup"/>
                <!-- ...other possible nodes... -->
            </xs:choice>
        </xs:sequence>
        <xs:attribute name="ID" type="xs:ID"/>
        <!-- ...other attributes... -->
    </xs:complexType>
    
    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(TypeName="StrucDoc.Paragraph", Namespace="urn:hl7-org:v3")]
    public partial class StrucDocParagraph {
    
        private StrucDocCaption captionField;
    
        private object[] itemsField;
    
        private string[] textField;
    
        private string idField;
    
        // ...fields for other attributes...
    
        /// <remarks/>
        public StrucDocCaption caption {
            get {
                return this.captionField;
            }
            set {
                this.captionField = value;
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("br", typeof(StrucDocBr))]
        [System.Xml.Serialization.XmlElementAttribute("sub", typeof(StrucDocSub))]
        [System.Xml.Serialization.XmlElementAttribute("sup", typeof(StrucDocSup))]
        // ...other possible nodes...
        public object[] Items {
            get {
                return this.itemsField;
            }
            set {
                this.itemsField = value;
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlTextAttribute()]
        public string[] Text {
            get {
                return this.textField;
            }
            set {
                this.textField = value;
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute(DataType="ID")]
        public string ID {
            get {
                return this.idField;
            }
            set {
                this.idField = value;
            }
        }
    
        // ...properties for other attributes...
    }
    
    <paragraph>first line<br /><br />third line</paragraph>
    
    itemsField = new object[]
    {
        new StrucDocBr(),
        new StrucDocBr(),
    };
    textField = new string[]
    {
        "first line",
        "third line",
    };
    
    <paragraph>
        <br />
        <br />first linethird line
    </paragraph>
    
    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(TypeName="StrucDoc.Paragraph", Namespace="urn:hl7-org:v3")]
    public partial class StrucDocParagraph {
    
        private StrucDocCaption captionField;
    
        private object[] itemsField;
    
        private string idField;
    
        // ...fields for other attributes...
    
        /// <remarks/>
        public StrucDocCaption caption {
            get {
                return this.captionField;
            }
            set {
                this.captionField = value;
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("br", typeof(StrucDocBr))]
        [System.Xml.Serialization.XmlElementAttribute("sub", typeof(StrucDocSub))]
        [System.Xml.Serialization.XmlElementAttribute("sup", typeof(StrucDocSup))]
        // ...other possible nodes...
        [System.Xml.Serialization.XmlTextAttribute(typeof(string))]
        public object[] Items {
            get {
                return this.itemsField;
            }
            set {
                this.itemsField = value;
            }
        }
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute(DataType="ID")]
        public string ID {
            get {
                return this.idField;
            }
            set {
                this.idField = value;
            }
        }
    
        // ...properties for other attributes...
    }
    
    <paragraph>first line<br /><br />third line</paragraph>
    
    itemsField = new object[]
    {
        "first line",
        new StrucDocBr(),
        new StrucDocBr(),
        "third line",
    };
    
    这正是我需要的,项目的顺序及其内容是正确的 如果我再次序列化,则结果再次正确:

    <paragraph>first line<br /><br />third line</paragraph>
    
    第一行

    第三行
    纪尧姆的回答为我指明了正确的方向,我也认为这一定是可能的。然后,在这个世界上:

    您可以将XmlTextAttribute应用于 返回一个值的字段或属性 字符串数组。你也可以申请 类型的数组的属性 对象,但必须设置类型 属性设置为字符串。在这种情况下,任何 插入到数组中的字符串是 序列化为XML文本


    所以序列化和反序列化现在工作正常,但我不知道是否还有其他副作用。也许用xsd.exe从这些类中生成模式已经不可能了,但无论如何我都不需要它。

    我遇到了与此相同的问题,并且遇到了改变由xsd.exe生成的.cs的解决方案。虽然它确实可以工作,但我对修改生成的代码感到不舒服,因为我需要记住在任何时候重新生成类时都要这样做。它还导致了一些笨拙的代码,这些代码必须针对mailto元素进行测试并转换到XmlNode[]

    我的解决方案是重新考虑xsd。我放弃了混合类型的使用,基本上定义了我自己的混合类型

    我有这个

    XML: <text>some text <mailto>me@email.com</mailto>some more text</text>
    
    <xs:complexType name="text" mixed="true">
        <xs:sequence>
          <xs:element minOccurs="0" maxOccurs="unbounded" name="mailto" type="xs:string" />
        </xs:sequence>
      </xs:complexType>
    
    XML:一些文本me@email.comsome更多文本
    
    改成

    XML: <mytext><text>some text </text><mailto>me@email.com</mailto><text>some more text</text></mytext>
    
    <xs:complexType name="mytext">
        <xs:sequence>
          <xs:choice minOccurs="0" maxOccurs="unbounded">
            <xs:element name="text">
              <xs:complexType>
                <xs:simpleContent>
                  <xs:extension base="xs:string" />
                </xs:simpleContent>
              </xs:complexType>
            </xs:element>
            <xs:element name="mailto">
              <xs:complexType>
                <xs:simpleContent>
                  <xs:extension base="xs:string" />
                </xs:simpleContent>
              </xs:complexType>
            </xs:element>
          </xs:choice>
        </xs:sequence>
      </xs:complexType>
    
    XML:一些文本me@email.comsome更多文本
    
    我生成的代码现在为我提供了一个myText类:

    public partial class myText{
    
        private object[] itemsField;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("mailto", typeof(myTextTextMailto))]
        [System.Xml.Serialization.XmlElementAttribute("text", typeof(myTextText))]
        public object[] Items {
            get {
                return this.itemsField;
            }
            set {
                this.itemsField = value;
            }
        }
    }
    
    公共部分类myText{
    私有对象[]项字段;
    /// 
    [System.Xml.Serialization.xmlementAttribute(“mailto”,typeof(mytextmailto))]
    [System.Xml.Serialization.xmlementAttribute(“text”,typeof(myTextText))]
    公共对象[]项{
    得到{
    返回此.itemsField;
    }
    设置{
    this.itemsField=值;
    }
    }
    }
    
    元素的顺序现在保留在序列化/反序列化中,但我确实需要根据类型
    mytextmailto
    mytextexttext
    测试/cast to/program


    我只是想把它作为一种对我有用的替代方法。

    当我尝试序列化对象时,这会导致InvalidOperationException(由于itemsField中的字符串,itemsField数组可能只包含由[XmlElement]指定的那些类型的对象)公共属性“Items”)的属性。您可以在此处找到帮助:是否存在架构验证警告?我在搜索过程中已找到该页,这与另一个问题有关。我的xml文档的模式是正确的,我在反序列化之前和序列化之后都对其进行了验证。但我刚才确实找到了问题的答案,您对itemsField数组的建议已经接近尾声,它只需要在生成的代码中进行进一步修改。我同意对于定义和使用自己的XML模式的人来说,您的方法是解决这个问题的首选方法。我的问题是,我没有选择修改XSD,因为它是由第三方控制的。因此,我不得不修改生成的类,这是出于您所说的原因,只有在没有其他方法的情况下才应该做的事情。这似乎不再起作用了(我的System.Xml版本是4.0.0)问题在于,它通过ItemsElementName字符串数组跟踪Items数组中元素的名称,并且元素必须1对1匹配。如果您使用的是通过反序列化XML文档填充的对象模型,则此要求会导致错误,因为