将对象序列化为XML并从XML中删除不需要的文本

时间:2011-10-06 09:37:54

标签: xml serialization removing-whitespace

我有一个对象需要序列化为XML,我使用以下代码来实现这一点:

 public static string Serialize(object obj)
    {
        using (var memoryStream = new MemoryStream())
        using (var reader = new StreamReader(memoryStream))
        {
            var serializer = new DataContractSerializer(obj.GetType());
            serializer.WriteObject(memoryStream, obj);
            memoryStream.Position = 0;
            return reader.ReadToEnd();
        }
    }

当我这样做时,我得到以下XML:

<TestRequestPOCO xmlns=\"http://schemas.datacontract.org/2004/07/GPTR.Model.POCOs\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">
    <AdditionalInformation>Additional Information</AdditionalInformation>
    <AddressLine1>6 MOUNT PLEASANT ROAD</AddressLine1>
    <AddressLine2>LEEDS</AddressLine2>
    <AddressLine3 i:nil=\"true\"/>
    <AddressLine4 i:nil=\"true\"/>
    <AntibioticTherapy i:nil=\"true\"/>
    <ClinicalInformation>Clinical Information</ClinicalInformation>
    <ClinicalInformationXml i:nil=\"true\"/>
    <Clinician>Dr NM BRYAN</Clinician>
    <ClinicianCode>4203845</ClinicianCode>
    <ClinicianShortCode :nil=\"true\"/>
    <Destination>1</Destination>
    <Dob>1992-02-29T00:00:00</Dob>
    <ExpectedDate>2011-10-06T10:22:57.096+01:00</ExpectedDate>
    <FirstName>ALISON</FirstName>
    <GenerateOrder>true</GenerateOrder>
    <HospitalNumber i:nil=\"true\"/>
    <IsFasting>false</IsFasting>
    <IsPrivatePatient>false</IsPrivatePatient>
    <IsSensitive>false</IsSensitive>
    <IsUrgent>false</IsUrgent>
    <Items>
        <RequestDataItem>
            <AdditionalInfo i:nil=\"true\"/>
            <Container i:nil=\"true\"/>
            <Description>Ferritin [Serum]</Description>
            <LIMSDeptName>CHM</LIMSDeptName>
            <ProfileNumber>1293</ProfileNumber>
            <QualifierCode i:nil=\"true\"/>
            <SiteCode i:nil=\"true\"/>
            <SpecimenType>Serum</SpecimenType>
            <UniqueTest>False</UniqueTest>
        </RequestDataItem>
    </Items>
    <Location>0</Location>
    <LocationName>The INPS Practice</LocationName>
    <LocationShortCode>W97046</LocationShortCode>
    <LocationTelephone>01792602898</LocationTelephone>
    <MiddleName i:nil=\"true\"/>
    <NhsNumber>5240022631</NhsNumber>
    <OrgCode>RRS</OrgCode>
    <Placer>Dr Sarah Saturn</Placer>
    <PostCode>CF31 5EP</PostCode>
    <Sex>Male</Sex>
    <Source>GPTR</Source>
    <SurName>WILLIAMS</SurName>
    <TelephoneNumber>01792776776</TelephoneNumber>
</TestRequestPOCO>"

正如你所看到的,它不能很好地处理空标签,而且我想删除根标签中的文本,所以我最终会得到这样的结果:

<TestRequestPOCO>
    <AdditionalInformation>Additional Information</AdditionalInformation>
    <AddressLine1>6 MOUNT PLEASANT ROAD</AddressLine1>
    <AddressLine2>LEEDS</AddressLine2>
    <AddressLine3/>
    <AddressLine4/>
    <AntibioticTherapy>
    <ClinicalInformation>Clinical Information</ClinicalInformation>
    <ClinicalInformationXml/>
    <Clinician>Dr NM BRYAN</Clinician>
    <ClinicianCode>4203845</ClinicianCode>
    <ClinicianShortCode/>
    <Destination>1</Destination>
    <Dob>1992-02-29T00:00:00</Dob>
    <ExpectedDate>2011-10-06T10:22:57.096+01:00</ExpectedDate>
    <FirstName>ALISON</FirstName>
    <GenerateOrder>true</GenerateOrder>
    <HospitalNumber/>
    <IsFasting>false</IsFasting>
    <IsPrivatePatient>false</IsPrivatePatient>
    <IsSensitive>false</IsSensitive>
    <IsUrgent>false</IsUrgent>
    <Items>
        <RequestDataItem>
            <AdditionalInfo/>
            <Container/>
            <Description>Ferritin [Serum]</Description>
            <LIMSDeptName>CHM</LIMSDeptName>
            <ProfileNumber>1293</ProfileNumber>
            <QualifierCode/>
            <SiteCode/>
            <SpecimenType>Serum</SpecimenType>
            <UniqueTest>False</UniqueTest>
        </RequestDataItem>
    </Items>
    <Location>0</Location>
    <LocationName>The INPS Practice</LocationName>
    <LocationShortCode>W97046</LocationShortCode>
    <LocationTelephone>01792602898</LocationTelephone>
    <MiddleName />
    <NhsNumber>5240022631</NhsNumber>
    <OrgCode>RRS</OrgCode>
    <Placer>Dr Sarah Saturn</Placer>
    <PostCode>CF31 5EP</PostCode>
    <Sex>Male</Sex>
    <Source>GPTR</Source>
    <SurName>WILLIAMS</SurName>
    <TelephoneNumber>01792776776</TelephoneNumber>
</TestRequestPOCO>"

有没有人知道如何解决这些问题并提出如上所述的XML字符串。

提前致谢。

1 个答案:

答案 0 :(得分:2)

要删除'null'值(即i:nil设置为true的值),需要将这些数据成员的DataMemberAttribute上的“EmitDefaultValue”设置为false。在.NET Framework中,类型具有默认值的概念。例如,对于任何引用类型,默认值为null,对于整数类型,它为0。

以下是一个例子:

[DataContract]
public class Employee
{
    // The CLR default for as string is a null value.
    // This will be written as <employeeName xsi:nill="true" />
    [DataMember]
    public string EmployeeName = null;

    // This will be written as <employeeID>0</employeeID>
    [DataMember]
    public int employeeID = 0;

    // The next three will not be written because the EmitDefaultValue = false.
    [DataMember(EmitDefaultValue = false)]
    public string position = null;
    [DataMember(EmitDefaultValue = false)]
    public int salary = 0;
    [DataMember(EmitDefaultValue = false)]
    public int? bonus = null;

    // This will be written as <targetSalary>57800</targetSalary> 
    [DataMember(EmitDefaultValue = false)]
    public int targetSalary = 57800;
}

在你这样做之前,我一定要仔细考虑。原因是当EmitDefaultValue设置为false时,它在架构中表示为特定于Windows Communication Foundation(WCF)的注释。没有可互操作的方式来表示此信息。特别是,模式中的“default”属性不用于此目的,minOccurs属性仅受IsRequired设置的影响,nillable属性仅受数据成员类型的影响。

至于删除各种其他无关的XML属性,你永远不能完全删除它,但是类似下面的代码可以帮助你确保它只在顶层发出一次:

注意突出显示的命名空间是如何定义五次的,当它只能在顶层定义一次时会产生很多膨胀。要解决此问题,您可以使用以下代码:

ser.WriteStartObject(writer, o);    
writer.WriteAttributeString("xmlns", "p", null, "some-reaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaally-long-namespace.com/");    
ser.WriteObjectContent(writer, o);    
ser.WriteEndObject(writer);