我当前的任务是编写一个用于处理HL7 CDA文件的类库。
这些XML文件是具有定义的HL7模式的.NET文件,因此我使用xsd.exe生成用于XML序列化和反序列化的.NET类。
XML Schema包含各种类型,这些类型包含mixed="true“属性,指定此类型的XML节点可以包含与其他XML节点混合的普通文本。
其中一种类型的XML schema的相关部分如下所示:
<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>
默认的序列化程序只是先序列化项目,然后序列化文本。
我尝试在StrucDocParagraph类上实现IXmlSerializable
,以便可以控制内容的反序列化和序列化,但这相当复杂,因为涉及的类太多了,而且我还没有找到解决方案,因为我不知道付出的努力是否有回报。
对于这个问题,有没有某种简单的解决方案,或者甚至可以通过IXmlSerializable
进行自定义序列化?或者我应该只使用XmlDocument
或XmlReader
/XmlWriter
来处理这些文档?
发布于 2010-04-06 18:03:33
为了解决这个问题,我不得不修改生成的类:
将字段从Text
属性移动到Items
属性,然后添加Text
property
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...
}
现在,如果我对进行反序列化,其中的段落节点如下所示:
<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>
Guillaume的回答给我指明了正确的方向,我也认为这肯定是可能的。然后在MSDN documentation to XmlTextAttribute
中出现了这样的情况:
您可以将XmlTextAttribute应用于返回字符串数组的字段或属性。也可以将该特性应用于Object类型的数组,但必须将type属性设置为string。在这种情况下,插入到数组中的任何字符串都被序列化为XML文本。
所以序列化和反序列化现在可以正常工作了,但我不知道是否还有其他副作用。也许再也不能用xsd.exe从这些类生成模式了,但无论如何我都不需要它了。
发布于 2011-03-24 22:43:23
我遇到了与此相同的问题,并遇到了这个修改xsd.exe生成的.cs的解决方案。尽管它确实起作用了,但我对更改生成的代码感到不舒服,因为我需要记住在任何时候重新生成类时都要这样做。它还导致了一些笨拙的代码,这些代码必须测试并转换为XmlNode[]中的mailto元素。
我的解决方案是重新考虑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
类型测试/强制转换/编程。
我只是想把它作为一种对我有效的替代方法。
发布于 2010-04-02 23:25:35
关于
itemsField = new object[]
{
"first line",
new StrucDocBr(),
new StrucDocBr(),
"third line",
};
https://stackoverflow.com/questions/2567414
复制相似问题