如何反序列化/序列化Microlife';c#中的xml

本文关键字:中的 xml Microlife 反序列化 序列化 | 更新日期: 2023-09-27 18:28:00

当我需要处理特定的xml文件时,我通常使用xsd2code生成c#类。但现在我有一个奇怪的xml文件被Microlife的血压分析器使用。xml文件将其模式作为额外的第一个元素包含在内部,如本例

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
    <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
        <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
            <xs:complexType>
                <xs:choice minOccurs="0" maxOccurs="unbounded">
                    <xs:element name="Patient">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name="ID" default="">
                                    <xs:simpleType>
                                        <xs:restriction base="xs:string">
                                            <xs:maxLength value="11"/>
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:element>
                                <xs:element name="FamilyName" type="xs:string" default="" minOccurs="0"/>
                                <xs:element name="GivenNames" type="xs:string" default="" minOccurs="0"/>
                                <xs:element name="Address" type="xs:string" default="" minOccurs="0"/>
                                <xs:element name="PhoneEmail" type="xs:string" default="" minOccurs="0"/>
                                <xs:element name="DateOfBirth" type="xs:dateTime" minOccurs="0"/>
                                <xs:element name="Weight" type="xs:decimal" default="0" minOccurs="0"/>
                                <xs:element name="Height" type="xs:decimal" default="0" minOccurs="0"/>
                                <xs:element name="Sex" type="xs:int" default="-1" minOccurs="0"/>
                                <xs:element name="Smoker" type="xs:int" default="-1" minOccurs="0"/>
                                <xs:element name="Diabetic" type="xs:int" default="-1" minOccurs="0"/>
                                <xs:element name="Cholestrol" type="xs:decimal" default="0" minOccurs="0"/>
                                <xs:element name="FamilyHistory" type="xs:string" default="" minOccurs="0"/>
                                <xs:element name="PatientNotes" type="xs:string" default="" minOccurs="0"/>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                    <xs:element name="MeasureRec">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name="ID" default="">
                                    <xs:simpleType>
                                        <xs:restriction base="xs:string">
                                            <xs:maxLength value="11"/>
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:element>
                                <xs:element name="RecID" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="MAM" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="Arrhythmia" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="ReadingDate" type="xs:dateTime" minOccurs="0"/>
                                <xs:element name="Sys" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="Dia" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="Map" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="PP" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="Pulse" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="Error" type="xs:int" default="0" minOccurs="0"/>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                    <xs:element name="Comment">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name="ID" default="">
                                    <xs:simpleType>
                                        <xs:restriction base="xs:string">
                                            <xs:maxLength value="11"/>
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:element>
                                <xs:element name="CommentID" type="xs:int"/>
                                <xs:element name="Degree" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="BeginDate" type="xs:dateTime" minOccurs="0"/>
                                <xs:element name="EndDate" type="xs:dateTime" minOccurs="0"/>
                                <xs:element name="Comment" type="xs:string" default="AAA" minOccurs="0"/>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                    <xs:element name="DataTransferLog">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name="ID" default="">
                                    <xs:simpleType>
                                        <xs:restriction base="xs:string">
                                            <xs:maxLength value="11"/>
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:element>
                                <xs:element name="RecID" type="xs:int" default="0" minOccurs="0"/>
                                <xs:element name="TransferDate" type="xs:dateTime" minOccurs="0"/>
                                <xs:element name="NumofRecord" type="xs:int" default="0" minOccurs="0"/>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                </xs:choice>
            </xs:complexType>
            <xs:unique name="Constraint1" msdata:PrimaryKey="true">
                <xs:selector xpath=".//Patient"/>
                <xs:field xpath="ID"/>
            </xs:unique>
            <xs:unique name="MeasureRec_Constraint1" msdata:ConstraintName="Constraint1">
                <xs:selector xpath=".//MeasureRec"/>
                <xs:field xpath="RecID"/>
            </xs:unique>
            <xs:unique name="Comment_Constraint1" msdata:ConstraintName="Constraint1">
                <xs:selector xpath=".//Comment"/>
                <xs:field xpath="CommentID"/>
            </xs:unique>
            <xs:unique name="Constraint2" msdata:PrimaryKey="true">
                <xs:selector xpath=".//Comment"/>
                <xs:field xpath="ID"/>
                <xs:field xpath="CommentID"/>
            </xs:unique>
            <xs:unique name="DataTransferLog_Constraint1" msdata:ConstraintName="Constraint1">
                <xs:selector xpath=".//DataTransferLog"/>
                <xs:field xpath="RecID"/>
            </xs:unique>
        </xs:element>
    </xs:schema>
    <Patient>
        <ID>A1234567890</ID>
        <FamilyName>Sample</FamilyName>
        <GivenNames>Patient</GivenNames>
        <Address>Max Schmidhelny Strasse 201 9435 Heerbrugg, Switzerland.</Address>
        <PhoneEmail>+41-71-727-7030/admin@microlife.ch</PhoneEmail>
        <DateOfBirth>1937-05-06T18:00:00+02:00</DateOfBirth>
        <Weight>94.34733</Weight>
        <Height>177.8</Height>
        <Sex>1</Sex>
        <Smoker>0</Smoker>
        <Diabetic>0</Diabetic>
        <Cholestrol>190</Cholestrol>
        <FamilyHistory>Not available.</FamilyHistory>
        <PatientNotes>This sample patient information will help you familiar with the "Blood Pressure Analyser" software by showing how new data is processed and displayed in graphical view. When adding a new patient, you can enter relevant patient details in this "Patient Notes" column</PatientNotes>
    </Patient>
    <MeasureRec>
        <ID>A1234567890</ID>
        <RecID>1000000</RecID>
        <MAM>0</MAM>
        <Arrhythmia>0</Arrhythmia>
        <ReadingDate>2009-03-21T12:16:00+01:00</ReadingDate>
        <Sys>143</Sys>
        <Dia>92</Dia>
        <Map>109</Map>
        <PP>51</PP>
        <Pulse>82</Pulse>
        <Error>0</Error>
    </MeasureRec>
    <MeasureRec>
        <ID>A1234567890</ID>
        <RecID>1000001</RecID>
        <MAM>0</MAM>
        <Arrhythmia>0</Arrhythmia>
        <ReadingDate>2009-03-22T04:21:00+01:00</ReadingDate>
        <Sys>136</Sys>
        <Dia>88</Dia>
        <Map>104</Map>
        <PP>48</PP>
        <Pulse>72</Pulse>
        <Error>0</Error>
    </MeasureRec>
    <MeasureRec>
        <ID>A1234567890</ID>
        <RecID>1000002</RecID>
        <MAM>1</MAM>
        <Arrhythmia>0</Arrhythmia>
        <ReadingDate>2009-03-22T10:58:00+01:00</ReadingDate>
        <Sys>140</Sys>
        <Dia>95</Dia>
        <Map>110</Map>
        <PP>45</PP>
        <Pulse>75</Pulse>
        <Error>0</Error>
    </MeasureRec>
    <MeasureRec>
        <ID>A1234567890</ID>
        <RecID>1000003</RecID>
        <MAM>0</MAM>
        <Arrhythmia>0</Arrhythmia>
        <ReadingDate>2009-03-23T02:25:00+01:00</ReadingDate>
        <Sys>133</Sys>
        <Dia>80</Dia>
        <Map>97</Map>
        <PP>53</PP>
        <Pulse>86</Pulse>
        <Error>0</Error>
    </MeasureRec>
    <Comment>
        <ID>A1234567890</ID>
        <CommentID>10000</CommentID>
        <Degree>3</Degree>
        <BeginDate>2009-04-02T02:11:47.933+02:00</BeginDate>
        <EndDate>2009-04-04T00:41:57.412+02:00</EndDate>
        <Comment>3 hours in health club
</Comment>
    </Comment>
    <Comment>
        <ID>A1234567890</ID>
        <CommentID>10001</CommentID>
        <Degree>2</Degree>
        <BeginDate>2009-04-06T23:33:27.303+02:00</BeginDate>
        <EndDate>2009-04-09T00:44:14.658+02:00</EndDate>
        <Comment>fatty food
party everyday</Comment>
    </Comment>
    <Comment>
        <ID>A1234567890</ID>
        <CommentID>10002</CommentID>
        <Degree>3</Degree>
        <BeginDate>2009-04-10T20:40:23.755+02:00</BeginDate>
        <EndDate>2009-04-17T13:16:50.703+02:00</EndDate>
        <Comment>travelling
irregular medication</Comment>
    </Comment>
    <Comment>
        <ID>A1234567890</ID>
        <CommentID>10003</CommentID>
        <Degree>2</Degree>
        <BeginDate>2009-04-04T18:57:22.877+02:00</BeginDate>
        <EndDate>2009-04-05T01:22:48.011+02:00</EndDate>
        <Comment>business lunch
400 c.c. alcohol
return visit 
in the afternoon</Comment>
    </Comment>
    <DataTransferLog>
        <ID>A1234567890</ID>
        <RecID>100002</RecID>
        <TransferDate>2009-03-27T10:19:03.0257856+01:00</TransferDate>
        <NumofRecord>3</NumofRecord>
    </DataTransferLog>
    <DataTransferLog>
        <ID>A1234567890</ID>
        <RecID>100003</RecID>
        <TransferDate>2009-04-05T11:19:03.0257856+02:00</TransferDate>
        <NumofRecord>3</NumofRecord>
    </DataTransferLog>
    <DataTransferLog>
        <ID>A1234567890</ID>
        <RecID>100004</RecID>
        <TransferDate>2009-04-11T11:19:03.0257856+02:00</TransferDate>
        <NumofRecord>3</NumofRecord>
    </DataTransferLog>
    <DataTransferLog>
        <ID>A1234567890</ID>
        <RecID>100005</RecID>
        <TransferDate>2009-04-18T11:19:03.0257856+02:00</TransferDate>
        <NumofRecord>3</NumofRecord>
    </DataTransferLog>
    <DataTransferLog>
        <ID>A1234567890</ID>
        <RecID>100006</RecID>
        <TransferDate>2009-04-25T11:19:03.0257856+02:00</TransferDate>
        <NumofRecord>3</NumofRecord>
    </DataTransferLog>
</NewDataSet>

我只能在没有xsd:schema部分的情况下处理此问题。如何序列化/反序列化完整的xml文件?

如何反序列化/序列化Microlife';c#中的xml

我能够从您的样本文件中加载NewDataSet和相应的Patient/Measurements等使用此代码段。

void Main()
{
    var path = @"... path to your sample xml";
    // you could skip this step, and deserialize directly from a file stream.
    var xml = XElement.Load(path);
    var nds = new XmlSerializer(typeof(NewDataSet)).Deserialize(xml.CreateReader());
    nds.Dump();
}
public class NewDataSet
{
    public Patient Patient { get; set; }
    [XmlElement("MeasureRec")]
    public MeasureRec[] Recs { get; set; }
    [XmlElement("Comment")]
    public Comment[] Comment { get; set; }
}
public class MeasureRec
{
    public int Pulse { get; set; }
}
public class Comment
{
    [XmlElement("Comment")]
    public string Text { get; set; }
}
public class Patient
{
    public string FamilyName { get; set; }
    public string GivenNames { get; set; }
}

给出一个NewDataSet实例,其族名称和给定名称填充在PatientMeasureRec和一些Comment中。

根据Jim的回答和评论,我认识到我在反序列化时的问题是xsd2code为每个元素生成一个Order XmlElementAttribute。如果我删除了这些属性,那么反序列化就可以很好地处理这个xml。如果我从xml中删除schema元素,它也可以工作(不更改生成的代码中的任何内容)。不幸的是,我不能通过为BP Analyzer编写xml来省略这个元素,因为只有当存在这个元素时,它才能导入xml文件。因此,我的最终解决方案是保留xsd2code生成的原始代码(来自给定的模式),并添加以下分部类,该类在读取时删除并记住schema元素,并在写入时将其插入回。

partial class NewDataSet
{
    [XmlIgnore]
    public XNode schema { get; set; }
    public static NewDataSet Read(string path)
    {
        var xml = XElement.Load(path);
        var schema = xml.FirstNode;
        xml.FirstNode.Remove();
        string xmlstring = xml.ToString();
        var ret = NewDataSet.Deserialize(xmlstring);
        ret.schema = schema;
        return ret;
    }
    public void Write(string path)
    {
        var XmlString = this.Serialize();
        var xml = XElement.Parse(XmlString);
        xml.AddFirst(this.schema);
        xml.Save(path);
    }
}

Serialize和Deserialize方法由xsd2code编写。