.Net XML序列化问题

时间:2009-07-08 06:33:10

标签: c# .net xml-serialization

我的困惑是,我使用.Net C#XMLSerializer来序列化自定义定义的类型,使用XSD工具从输入原始XML文件生成的schema / cs文件。但生成的序列化XML文件命名空间与原始XML输入文件不同。特别是从原始XML文件,Envelope属于命名空间soapenv,但在序列化XML文件中,Envelope属于默认命名空间。有什么想法是错的吗?

以下是我如何使用XSD工具从XML输入文件XMLFile1.xml为自定义定义类型生成模式文件和cs文件,

BTW:可以从

下载XML文件

http://www.mediafire.com/?nwngwzz3gmm

D:\>xsd XMLFile1.xml
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.3038]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'D:\XMLFile1.xsd'.

D:\>xsd XMLFile1.xsd XMLFile1_app1.xsd /classes
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.3038]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'D:\XMLFile1_XMLFile1_app1.cs'.

以下是我如何使用C#代码序列化文件并输出到TestOutputFile.xml,

static void Main(string[] args)
{
    Envelope en = new Envelope();
    en.Items = new EnvelopeBody[1];
    en.Items[0] = new EnvelopeBody();
    en.Items[0].QueryResponse = new QueryResponseFaculties[1];
    en.Items[0].QueryResponse[0] = new QueryResponseFaculties();
    en.Items[0].QueryResponse[0].Name = "John";

    XmlSerializer serializer =
     new XmlSerializer(typeof(Envelope));
    TextWriter writer = new StreamWriter("TestOutputFile.xml");

    serializer.Serialize(writer, en);
    writer.Close();

    return;
}

原始XML文件是

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <QueryResponse xmlns="http://schemas.mycorp.com/test">
      <Faculties>
        <Name>
          John
        </Name>
      </Faculties>
    </QueryResponse>
  </soapenv:Body>
</soapenv:Envelope>

序列化的XML文件是

<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <QueryResponse xmlns="http://schemas.mycorp.com/test">
      <Faculties>
        <Name>John</Name>
      </Faculties>
    </QueryResponse>
  </Body>
</Envelope>

编辑1:

目前的代码是,

static void Main(string[] args)
{
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
    ns.Add("", "http://schemas.mycorp.com/test");
    ns.Add("xsd", "http://www.w3.org/2001/XMLSchema");
    ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");

    Envelope en = new Envelope();
    en.Items = new EnvelopeBody[1];
    en.Items[0] = new EnvelopeBody();
    en.Items[0].QueryResponse = new QueryResponseFaculties[1];
    en.Items[0].QueryResponse[0] = new QueryResponseFaculties();
    en.Items[0].QueryResponse[0].Name = "John";

    XmlSerializer serializer =
     new XmlSerializer(typeof(Envelope));
    TextWriter writer = new StreamWriter("TestOutputFile.xml");

    serializer.Serialize(writer, en, ns);
    writer.Close();

    return;
}

当前输出(序列化XML文件)是

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://schemas.mycorp.com/test"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <QueryResponse>
      <Faculties>
        <Name>John</Name>
      </Faculties>
    </QueryResponse>
  </soapenv:Body>
</soapenv:Envelope>

我希望输出为(注意字符串xmlns =“http://schemas.mycorp.com/test”的位置),

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <QueryResponse xmlns="http://schemas.mycorp.com/test">
      <Faculties>
        <Name>John</Name>
      </Faculties>
    </QueryResponse>
  </soapenv:Body>
</soapenv:Envelope>
提前谢谢, 乔治

2 个答案:

答案 0 :(得分:3)

它们不可互换吗?在一个方面,它使用xmlns在元素上设置名称空间,在另一个中使用xmlns:soapenv别名 - 但意思相同,而IMO第二个版本更清晰。

XmlSerializerNamespaces类可以解决这个问题;完整的例子:

using System;
using System.Xml.Serialization;
[XmlRoot(Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope {
    public Body Body { get; set; }
}
public class Body {
    [XmlElement(Namespace="http://schemas.mycorp.com/test")]
    public QueryResponse QueryResponse { get; set; }
}
public class QueryResponse {
    public Faculties Faculties { get; set; }
}
public class Faculties {
    public string Name { get; set; }
}
static class Program {
    static void Main() {
        XmlSerializer ser = new XmlSerializer(typeof(Envelope));
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
        ns.Add("xsd", "http://www.w3.org/2001/XMLSchema");
        ns.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
        Envelope env = new Envelope {
            Body = new Body {
                QueryResponse = new QueryResponse {
                     Faculties = new Faculties { Name = "John"}
                }
            }
        };
        ser.Serialize(Console.Out, env, ns);
    }
}

输出(@encoding是因为Console.Out):

<?xml version="1.0" encoding="ibm850"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <QueryResponse xmlns="http://schemas.mycorp.com/test">
      <Faculties>
        <Name>John</Name>
      </Faculties>
    </QueryResponse>
  </soapenv:Body>
</soapenv:Envelope>

答案 1 :(得分:3)

您需要使用XmlSerializerNamespaces类来设置命名空间,然后在序列化时,您需要将XmlSerializerNamespces的实例与对象一起传递。您还需要使用XmlRoot和XmlElement属性设置类和/或属性的命名空间:

static void Main(string[] args)
{
    Envelope en = new Envelope();
    en.Items = new EnvelopeBody[1];
    en.Items[0] = new EnvelopeBody();
    en.Items[0].QueryResponse = new QueryResponseFaculties[1];
    en.Items[0].QueryResponse[0] = new QueryResponseFaculties();
    en.Items[0].QueryResponse[0].Name = "John";

    XmlSerializer serializer =
     new XmlSerializer(typeof(Envelope));
    TextWriter writer = new StreamWriter("TestOutputFile.xml");

    XmlSerlializerNamespaces xsn = new XmlSerializerNamespaces();
    xsn.Add("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");

    serializer.Serialize(writer, en, xsn);
    writer.Close();

    return;
}

[XmlRoot(Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
class Envelope
{
    // ...
}