简体   繁体   English

如何在C#中反序列化/序列化Microlife的xml

[英]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. 当我需要处理特定的xml文件时,通常会使用xsd2code生成c#类。 But now I have a strange xml file used by Microlife's Blood Pressure Analyser. 但是现在,我有了Microlife的血压分析仪使用的一个奇怪的xml文件。 The xml file contains its schema inside as an extra first element, like this example 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>

I can handle this only without the xsd:schema part. 我只能在没有xsd:schema部分的情况下进行处理。 How to serialize/deserialize the complete xml file? 如何对完整的xml文件进行序列化/反序列化?

I am able to load a NewDataSet, and corresponding Patient / Measurements etc from your sample file using this snippet. 我可以使用此代码片段从您的样本文件中加载NewDataSet以及相应的Patient / Measurement等。

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). 提供一个NewDataSet实例,该实例具有族名,并在PatientMeasureRec和一些Comment填充给定名称。

Based on Jim's answer and comments, I recognised, that my problem at deserialize was that xsd2code generates an Order XmlElementAttribute for each element. 根据Jim的回答和评论,我认识到,反序列化的问题是xsd2code为每个元素生成一个Order XmlElementAttribute。 If I remove these attributes, the deserialization works fine for this xml. 如果我删除这些属性,则反序列化对于该xml来说工作正常。 It also works (without changing anything in the generated code) if I remove the schema element from the xml. 如果我从xml中删除schema元素,它也将起作用(不更改生成的代码中的任何内容)。 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. 不幸的是,我无法通过为BP分析器编写xml来省略此元素,因为只有存在该元素时,它才能导入xml文件。 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. 因此,我的最终解决方案是保留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);
    }
}

The Serialize and Deserialize methods are written by xsd2code. Serialize和Deserialize方法由xsd2code编写。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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