简体   繁体   中英

How to deserialize/serialize Microlife's xml in c#

When I need to handle a specific xml file, I usually generate c# classes using xsd2code. But now I have a strange xml file used by Microlife's Blood Pressure Analyser. The xml file contains its schema inside as an extra first element, like this example

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

I can handle this only without the xsd:schema part. How to serialize/deserialize the complete xml file?

I am able to load a NewDataSet, and corresponding Patient / Measurements etc from your sample file using this snippet.

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

Gives a NewDataSet instance, with the family name, and given name populated in Patient , MeasureRec , and some Comment (s).

Based on Jim's answer and comments, I recognised, that my problem at deserialize was that xsd2code generates an Order XmlElementAttribute for each element. If I remove these attributes, the deserialization works fine for this xml. It also works (without changing anything in the generated code) if I remove the schema element from the xml. Unfortunately, I cannot omit this element by writing an xml for the BP Analyzer, because it can import the xml file only if it this element is present. So, my final solution is keeping the original code generated by xsd2code (from the given schema) and adding the following partial class that removes and memorizes the schema element at reading, and inserts it back at writing.

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);
    }
}

The Serialize and Deserialize methods are written by xsd2code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM