[英]Correct XML serialization and deserialization of “mixed” types in .NET
我當前的任務涉及編寫用於處理HL7 CDA文件的類庫。
這些HL7 CDA文件是具有定義的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...
}
如果我反序列化段落節點如下所示的XML元素:
<paragraph>first line<br /><br />third line</paragraph>
結果是像這樣讀取item和text數組:
itemsField = new object[]
{
new StrucDocBr(),
new StrucDocBr(),
};
textField = new string[]
{
"first line",
"third line",
};
由此無法確定文本和其他節點的確切順序。
如果我再次序列化它,結果將看起來完全像這樣:
<paragraph>
<br />
<br />first linethird line
</paragraph>
默認的序列化程序只會先序列化項目,然后再序列化文本。
我嘗試在StrucDocParagraph類上實現IXmlSerializable
,以便可以控制內容的反序列化和序列化,但是由於涉及的類太多,而且還沒有找到解決方案,因為它不知道是否存在,所以它相當復雜。努力得到回報。
是否有某種簡單的解決方法來解決此問題,或者是否有可能通過IXmlSerializable
執行自定義序列化? 還是應該只使用XmlDocument
或XmlReader
/ XmlWriter
處理這些文檔?
為了解決這個問題,我不得不修改生成的類:
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...
}
現在,如果我反序列化段落節點如下所示的XML元素:
<paragraph>first line<br /><br />third line</paragraph>
結果是像這樣讀取item數組:
itemsField = new object[]
{
"first line",
new StrucDocBr(),
new StrucDocBr(),
"third line",
};
這正是我所需要的 ,項目的順序及其內容是正確的 。
如果我再次序列化此結果,則結果再次正確:
<paragraph>first line<br /><br />third line</paragraph>
正確的方向指向我的就是紀堯姆(Guillaume)的答案,我還認為這樣做一定是可能的。 然后在MSDN文檔中有XmlTextAttribute
:
您可以將XmlTextAttribute應用於返回字符串數組的字段或屬性。 您也可以將屬性應用於Object類型的數組,但是必須將Type屬性設置為string。 在這種情況下,插入到數組中的所有字符串都將序列化為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: <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>
現在,我生成的代碼為我提供了一個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;
}
}
}
元素的順序現在保留在序列化/反序列化中,但是我必須針對myTextTextMailto
和myTextText
類型進行測試/ myTextTextMailto
轉換/編程。
只是以為我會將它作為對我有用的替代方法。
關於什么
itemsField = new object[]
{
"first line",
new StrucDocBr(),
new StrucDocBr(),
"third line",
};
?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.