Сериализация XML с пространством имен - PullRequest
0 голосов
/ 22 декабря 2018

Я хочу создать приведенный ниже XML-запрос.Когда я использую инструмент XML для C #, чтобы сгенерировать классы для этого запроса, а затем сериализовать для вызова веб-службы, мой сгенерированный запрос не имеет 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 голосов
/ 22 декабря 2018

Вот один из способов достижения желаемого результата.Я проверил, используя следующую структуру класса.Ничего особенного в этом нет, кроме наличия свойства SchemaLocation в DCTRequest, которое гарантирует, что вы получите xsi:schemaLocation в конечном XML, и установки внешнего пространства имен на "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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...