使用命名空间序列化XML

时间:2018-12-22 07:21:42

标签: c# xml serialization

我想生成以下XML请求。当我使用XML to C#工具生成此请求的类,然后序列化以调用Webservice时,我生成的请求的根目录中没有p:,因此我的请求失败。有人可以帮忙吗?

<?xml version="1.0" encoding="utf-8"?>
<p:DCTRequest xmlns:p="http://www.dhl.com" xmlns:p1="http://www.dhl.com/datatypes" xmlns:p2="http://www.dhl.com/DCTRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.dhl.com DCT-req.xsd ">
  <GetQuote>
    <Request>
      <ServiceHeader>
        <MessageTime>2002-08-20T11:28:56.000-08:00</MessageTime>
        <MessageReference>1234567890123456789012345678901</MessageReference>
        <SiteID>DDDDD</SiteID>
        <Password>XXXX</Password>
      </ServiceHeader>
    </Request>
  </GetQuote>
</p:DCTRequest>

这是我用于序列化类的代码:

public static string Serialize(object dataToSerialize) 
{ 
    if (dataToSerialize == null) return null; 
    using (Utf8StringWriter stringwriter = new Utf8StringWriter()) 
    { 
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();  
        ns.Add("p", "DCTRequest"); 
        var serializer = new XmlSerializer(dataToSerialize.GetType()); 
        serializer.Serialize(stringwriter, dataToSerialize); 
        return stringwriter.ToString(); 
    } 
}

1 个答案:

答案 0 :(得分:1)

这是您可以获得期望结果的一种方法。我使用以下类结构进行了测试。除了在DCTRequest上具有SchemaLocation属性以确保您在最终XML中获得xsi:schemaLocation并将外部名称空间设置为“ http://www.dhl.com”之外,对此没有什么特别的以后给它加上p前缀。

[XmlRoot(Namespace = "http://www.dhl.com")]
public class DCTRequest
{

    [XmlAttribute(AttributeName = "schemaLocation", Form = System.Xml.Schema.XmlSchemaForm.Qualified, Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public string SchemaLocation { get; set; }
    [XmlElement(Namespace = "")]
    public GetQuote GetQuote { get; set; }
}

public class GetQuote
{
    public Request Request { get; set; }
}

public class Request
{
    public ServiceHeader ServiceHeader { get; set; }
}

public class ServiceHeader
{
    public DateTime MessageTime { get; set; }
    public string MessageReference { get; set; }
    public string SideID { get; set; }
    public string Password { get; set; }
}

我调整了您的序列化方法,如下所示。您在这里错了两件事:

  • 您已经传递了对象/元素名称DCTRequest作为名称空间。错了,名称空间的格式为http://www.mynamespace.com/whatever。就您而言,您有xmlns:p="http://www.dhl.com"p被称为名称空间前缀。这是引用完整名称空间http://www.dhl.com的简便方法。
  • 您不会在对XmlSerializerNamespaces的调用中传递serializer.Serialize的实例,因此该实例未被使用且不做任何事情。

这是固定版本:

public static string Serialize(object dataToSerialize)
{
    if (dataToSerialize == null) return null;
    using (StringWriter stringWriter = new StringWriter())
    {
        XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
        namespaces.Add("p", "http://www.dhl.com");
        namespaces.Add("p1", "http://www.dhl.com/datatypes");
        namespaces.Add("p2", "http://www.dhl.com/DCTRequestdatatypes");
        namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
        var serializer = new XmlSerializer(dataToSerialize.GetType());
        serializer.Serialize(stringWriter, dataToSerialize, namespaces);
        return stringWriter.ToString();
    }        
}

如果将它们放在一起并像这样调用:

var dctRequest = new DCTRequest()
{
    SchemaLocation = "http://www.dhl.com DCT-req.xsd ",
    GetQuote = new GetQuote()
    {
        Request = new Request()
        {
            ServiceHeader = new ServiceHeader()
            {
                MessageTime = DateTime.Now,
                MessageReference = "1234567890123456789012345678901",
                SideID = "DDDDD",
                Password = "XXXX"
            }
        }
    }
};

var xml = Serialize(dctRequest);

然后您将获得所需的XML:

<?xml version="1.0" encoding="utf-16"?>
<p:DCTRequest xmlns:p2="http://www.dhl.com/DCTRequestdatatypes" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p1="http://www.dhl.com/datatypes" xmlns:p="http://www.dhl.com" xsi:schemaLocation="http://www.dhl.com DCT-req.xsd ">
  <GetQuote>
    <Request>
      <ServiceHeader>
        <MessageTime>2018-12-22T10:09:06.6530604+00:00</MessageTime>
        <MessageReference>1234567890123456789012345678901</MessageReference>
        <SideID>DDDDD</SideID>
        <Password>XXXX</Password>
      </ServiceHeader>
    </Request>
  </GetQuote>
</p:DCTRequest>