Ste*_*bka 18 .net c# xml-serialization
我当前的任务涉及编写用于处理HL7 CDA文件的类库.
这些HL7 CDA文件是具有已定义XML模式的XML文件,因此我使用xsd.exe生成用于XML序列化和反序列化的.NET类.
XML Schema包含各种类型,其中包含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>
Run Code Online (Sandbox Code Playgroud)
将生成的代码这种类型如下:
/// <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...
}
Run Code Online (Sandbox Code Playgroud)
如果我反序列化段落节点如下所示的XML元素:
<paragraph>first line<br /><br />third line</paragraph>
Run Code Online (Sandbox Code Playgroud)
该结果是,项目和文本阵列读这样的:
itemsField = new object[]
{
new StrucDocBr(),
new StrucDocBr(),
};
textField = new string[]
{
"first line",
"third line",
};
Run Code Online (Sandbox Code Playgroud)
由此无法确定文本和其他节点的确切顺序.
如果我再次序列化,结果看起来如下:
<paragraph>
<br />
<br />first linethird line
</paragraph>
Run Code Online (Sandbox Code Playgroud)
默认的序列化程序只是首先序列化项目,然后是文本.
我尝试IXmlSerializable在StrucDocParagraph类上实现,以便我可以控制内容的反序列化和序列化,但它相当复杂,因为涉及的类很多,我还没有找到解决方案因为我不知道是否努力得到回报.
是否有某种简单的解决方法来解决这个问题,或者甚至可以通过自定义序列化来实现IXmlSerializable?或者我应该只使用XmlDocument或XmlReader/ XmlWriter来处理这些文件?
Ste*_*bka 22
要解决这个问题,我不得不修改生成的类:
XmlTextAttribute从Text属性移动到Items属性并添加参数Type = typeof(string)Text属性textField字段结果生成的代码(已修改)如下所示:
/// <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...
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我反序列化段落节点如下所示的XML元素:
<paragraph>first line<br /><br />third line</paragraph>
Run Code Online (Sandbox Code Playgroud)
该结果是该项目数组这样写的:
itemsField = new object[]
{
"first line",
new StrucDocBr(),
new StrucDocBr(),
"third line",
};
Run Code Online (Sandbox Code Playgroud)
这正是我需要的,项目的顺序和内容是正确的.
如果我再次序列化,结果再次正确:
<paragraph>first line<br /><br />third line</paragraph>
Run Code Online (Sandbox Code Playgroud)
让我指向正确方向的是Guillaume的答案,我也认为必须这样.然后在MSDN文档中有这样的XmlTextAttribute:
您可以将XmlTextAttribute应用于返回字符串数组的字段或属性.您还可以将该属性应用于Object类型的数组,但必须将Type属性设置为string.在这种情况下,插入到数组中的任何字符串都被序列化为XML文本.
因此序列化和反序列化工作现在正确,但我不知道是否还有其他副作用.也许不可能再用xsd.exe从这些类生成一个模式,但我还是不需要它.