2015-12-23 256 views
0

當我需要處理特定的xml文件時,我通常使用xsd2code生成c#類。但現在我有一個奇怪的XML文件使用Microlife的血壓分析儀。 XML文件包含的架構內作爲一個額外的第一要素,像這樣的例子如何在c中反序列化/序列化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/[email protected]</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:架構的一部分。如何序列化/反序列化完整的xml文件?

回答

1

我可以使用此代碼段從示例文件 中加載NewDataSet以及相應的患者/測量等。

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(S)。

+0

很好,這真的有效。但是另一個方向呢?我怎樣才能把額外的元素放入序列化的xml中? (當然,我可以使用字符串操作來完成這項工作,但是如果有更優雅的解決方案,這將會很不錯)。 – mma

+0

...除了'nds.Dump();'它是什麼? – mma

+1

轉儲在linqpad中使用,如果粘貼代碼並運行它,結果將顯示 – Jim

0

基於Jim的回答和評論,我認識到,我反序列化的問題在於xsd2code爲每個元素生成一個Order XmlElementAttribute。如果我刪除這些屬性,則反序列化對此xml工作正常。如果我從xml中刪除schema元素,它也可以工作(不會更改生成的代碼中的任何內容)。不幸的是,我不能通過爲BP分析器編寫一個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編寫。