正确的XML序列化和&QUOT反序列化;混合"在.NET类型 [英] Correct XML serialization and deserialization of "mixed" types in .NET

查看:199
本文介绍了正确的XML序列化和&QUOT反序列化;混合"在.NET类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的当前任务需要编写一个类库,用于处理HL7 CDA文件。
这些HL7 CDA文件是有定义的XML架构的XML文件,所以我用XSD.EXE生成.NET类的XML序列化和反序列化。

My current task involves writing a class library for processing HL7 CDA files.
These HL7 CDA files are XML files with a defined XML schema, so I used xsd.exe to generate .NET classes for XML serialization and deserialization.

XML架构包含含有在混合=true属性下,指定此类型的XML节点可以含有普通的文本与其他XML节点混合各种类型。
XML模式作为这些类型之一的相关部分看起来是这样的:

The XML Schema contains various types which contain the mixed="true" attribute, specifying that an XML node of this type may contain normal text mixed with other XML nodes.
The relevant part of the XML schema for one of these types looks like this:

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

生成code 作为这种类型看起来是这样的:

The generated code for this type looks like this:

/// <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...
}

如果我反序列化 XML元素所在的段落节点是这样的:

If I deserialize an XML element where the paragraph node looks like this:

<paragraph>first line<br /><br />third line</paragraph>

结果是该项目和文本阵列读这样的:

The result is that the item and text arrays are read like this:

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

从这个没有可能的方式来确定文本和其他节点的确切顺序。
如果我的连载这一次,结果看上去完全是这样的:

From this there is no possible way to determine the exact order of the text and the other nodes.
If I serialize this again, the result looks exactly like this:

<paragraph>
    <br />
    <br />first linethird line
</paragraph>

默认串行只是,然后再序列化项目的文本。

The default serializer just serializes the items first and then the text.

我试图实施的IXmlSerializable 在StrucDocParagraph类,这样我可以控制的内容反序列化和序列化,但它是相当复杂的,因为有这么多的班参与,我没来一个解决方案,但因为我不知道功夫不负有心人。

I tried implementing IXmlSerializable on the StrucDocParagraph class so that I could control the deserialization and serialization of the content, but it's rather complex since there are so many classes involved and I didn't come to a solution yet because I don't know if the effort pays off.

有某种简单的解决方法这个问题,或者是它甚至有可能被通过的IXmlSerializable 做自定义序列化? 或者我应该只使用的XmlDocument 的XmlReader / 的XmlWriter 来处理这些文件?

Is there some kind of easy workaround to this problem, or is it even possible by doing custom serialization via IXmlSerializable? Or should I just use XmlDocument or XmlReader/XmlWriter to process these documents?

推荐答案

要解决这个问题,我不得不修改生成的类:

To solve this problem I had to modify the generated classes:

  1. 将在 XmlTextAttribute 文本属性设置为产品属性并添加参数键入= typeof运算(字符串)
  2. 删除文本属性
  3. 删除 textField的字段
  1. Move the XmlTextAttribute from the Text property to the Items property and add the parameter Type = typeof(string)
  2. Remove the Text property
  3. Remove the textField field

结果在生成code(修改)是这样的:

/// <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...
}

现在,如果我的反序列化 XML元素所在的段落节点是这样的:

Now if I deserialize an XML element where the paragraph node looks like this:

<paragraph>first line<br /><br />third line</paragraph>

结果是该项目的数组是这样写的:

The result is that the item array is read like this:

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

这是正是我需要的项,顺序和内容是正确
如果我的连载这一次,结果又是正确的:

This is exactly what I need, the order of the items and their content is correct.
And if I serialize this again, the result is again correct:

<paragraph>first line<br /><br />third line</paragraph>

什么我指出了正确的方向是由纪尧姆答案,我还以为是什么可能是这样。然后有这个在<一个href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmltextattribute%28VS.85%29.aspx">MSDN文档 XmlTextAttribute

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

You can apply the XmlTextAttribute to a field or property that returns an array of strings. You can also apply the attribute to an array of type Object but you must set the Type property to string. In that case, any strings inserted into the array are serialized as XML text.

因此​​,序列化和反序列化工作正确的,但我不知道是否有其他的副作用。也许这是不可能生成这些类与XSD.EXE一个模式了,但我不需要反正。

So the serialization and deserialization work correct now, but I don't know if there are any other side effects. Maybe it's not possible to generate a schema from these classes with xsd.exe anymore, but I don't need that anyway.

这篇关于正确的XML序列化和&QUOT反序列化;混合&QUOT;在.NET类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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