【问题标题】:C# XmlSerializer define namespace with prefix in a child nodeC# XmlSerializer 在子节点中定义带前缀的命名空间
【发布时间】:2020-09-23 00:25:26
【问题描述】:

我需要用 C# 创建一个 XML 文档,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Container>
  <Info>
    <request xmlns:a="http://www.UKMail.com/Services/Contracts/DataContracts">
      <a:AuthenticationToken>token</a:AuthenticationToken>
      <a:Username>username</a:Username>
      <a:ConsignmentNumber>12345</a:ConsignmentNumber>
    </request>
  </Info>
</Container>

关键部分是带有前缀 (xmlns:a=...) 的命名空间定义位于子节点中,而不是根节点中。到目前为止,我只能制作这份文件:

<?xml version="1.0" encoding="utf-8"?>
<Container xmlns:a="http://www.UKMail.com/Services/Contracts/DataContracts">
  <Info>
    <a:request>
      <a:AuthenticationToken>token</a:AuthenticationToken>
      <a:Username>username</a:Username>
      <a:ConsignmentNumber>12345</a:ConsignmentNumber>
    </a:request>
  </Info>
</Container>

这被 Web 服务拒绝 - 如果您将 xmlns:a.. 部分移动到请求节点,Web 服务会对此感到满意。

这就是我目前生成 XML 的方式:

class Program
    {
        static void Main(string[] args)
        {
            SerializeObject("XmlNamespaces.xml");
        }

        public static void SerializeObject(string filename)
        {
            var mySerializer = new XmlSerializer(typeof(Container));
            // Writing a file requires a TextWriter.
            TextWriter myWriter = new StreamWriter(filename);

            // Creates an XmlSerializerNamespaces and adds two
            // prefix-namespace pairs.
            var myNamespaces = new XmlSerializerNamespaces();
            myNamespaces.Add("a", "http://www.UKMail.com/Services/Contracts/DataContracts");


            Container container = new Container
            {
                Info = new CancelConsignmentRequest
                {
                    request = new CancelConsignmentRequestInfo
                    {
                        AuthenticationToken = "token",
                        ConsignmentNumber = "12345",
                        Username = "username"
                    }
                }
            };

            mySerializer.Serialize(myWriter, container, myNamespaces);
            myWriter.Close();
        }
    }

    public class Container
    {
        public CancelConsignmentRequest Info { get; set; } = new CancelConsignmentRequest();
    }

    [XmlRoot(Namespace = "http://www.UKMail.com/Services/Contracts/ServiceContracts")]
    public class CancelConsignmentRequest
    {
        [XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts")]
        public CancelConsignmentRequestInfo request { get; set; } = new CancelConsignmentRequestInfo();
    }

    public class CancelConsignmentRequestInfo
    {
        [XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 0)]
        public string AuthenticationToken { get; set; }
        [XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 1)]
        public string Username { get; set; }

        [XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 2)]
        public string ConsignmentNumber { get; set; }
    }

我无法弄清楚如何将命名空间定义带前缀放置在其中一个子节点中。请问有谁知道如何在C#中做到这一点?谢谢。

【问题讨论】:

  • “关键部分是......这被网络服务拒绝了” - 不应该是向服务作者报告错误吗?
  • @Sinatr XML 仍然有效,不是吗?因此,您应该能够使用 C# 生成它。
  • 第二个 XML 也是有效的。为什么服务不支持xml标准?
  • 一种奇怪的方法是在没有命名空间的情况下序列化 xml,然后用XmlDocument 读回它,并用SetAttribute 重载接受URI 设置命名空间。
  • 这能回答你的问题吗? XML namespace on child element

标签: c# xml xml-namespaces


【解决方案1】:

这是可能的。下面的代码可以满足您的要求。

class Program
{
    static void Main(string[] args)
    {
        SerializeObject("XmlNamespaces.xml");
    }

    public static void SerializeObject(string filename)
    {
        var mySerializer = new XmlSerializer(typeof(Container));
        // Writing a file requires a TextWriter.
        TextWriter myWriter = new StreamWriter(filename);

        // Creates an XmlSerializerNamespaces and adds two
        // prefix-namespace pairs.
        var myNamespaces = new XmlSerializerNamespaces();
        //myNamespaces.Add("a", "http://www.UKMail.com/Services/Contracts/DataContracts");

        Container container = new Container
        {
            Info = new CancelConsignmentRequest
            {
                request = new CancelConsignmentRequestInfo
                {
                    AuthenticationToken = "token",
                    ConsignmentNumber = "12345",
                    Username = "username"
                }
            }
        };

        mySerializer.Serialize(myWriter, container, myNamespaces);
        myWriter.Close();
    }
}

public class Container
{
    public CancelConsignmentRequest Info { get; set; } = new CancelConsignmentRequest();
}

public class CancelConsignmentRequest
{
    public CancelConsignmentRequestInfo request { get; set; } = new CancelConsignmentRequestInfo();
}

[XmlRoot(Namespace = "http://www.UKMail.com/Services/Contracts/ServiceContracts")]
public class CancelConsignmentRequestInfo
{
    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces(
        new[] { new XmlQualifiedName("a", "http://www.UKMail.com/Services/Contracts/DataContracts"), });
    [XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 0)]
    public string AuthenticationToken { get; set; }
    [XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 1)]
    public string Username { get; set; }

    [XmlElement(Namespace = "http://www.UKMail.com/Services/Contracts/DataContracts", Order = 2)]
    public string ConsignmentNumber { get; set; }
}

【讨论】:

  • 谢谢 - 它仍然在请求节点的开头留下 a:,这是 Web 服务不喜欢的。我已编辑您的回复以删除注释,然后给我所需的输出。
猜你喜欢
  • 2011-11-12
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多