XML 包含命名空间为空 URI 的元素会中断反序列化

XML contains element with the namespace as empty URI breaks deserialization

提问人:user2838376 提问时间:9/28/2023 最后编辑:Yong Shunuser2838376 更新时间:9/28/2023 访问量:29

问:

我有一个具有以下结构的 XML:

<?xml version="1.0" encoding="utf-8"?>
<ClientInfo xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/">
  <Error>0</Error>
  <ErrorMsg />
  <doc>
    <NewDataSet xmlns="">
      <Table>
        <SEGMENT>123456</SEGMENT>
      </Table>
    </NewDataSet>
  </doc>
</ClientInfo>

请注意标签。 我正在尝试使用以下类反序列化此 XML:NewDataSet xmlns=""ClientInfo

[XmlRoot(ElementName = "Table")]
public partial class Table
{
    [XmlElement(ElementName = "SEGMENT")]
    public string SEGMENT { get; set; }
}

[XmlRoot(ElementName = "NewDataSet")]
public partial class MyDataSet
{
    [XmlElement(ElementName = "Table")]
    public Table Table { get; set; }
}

[XmlRoot(ElementName = "doc")]
public class Doc
{

    [XmlElement(ElementName = "NewDataSet")]
    public MyDataSet MyDataSet { get; set; }
}

[Serializable, XmlRoot(ElementName = "ClientInfo", Namespace = "http://tempuri.org/")]
public partial class ClientInfo
{

    [XmlElement(ElementName = "Error")]
    public int Error { get; set; }

    [XmlElement(ElementName = "ErrorMsg")]
    public object ErrorMsg { get; set; }

    [XmlElement(ElementName = "doc")]
    public Doc Doc { get; set; }
}

结果,从生成的对象返回 .MyDataSetxmlResult.Doc.MyDataSet.Table.SEGMENTnull

没有一切正常。现在这个属性是留下来的。不能真的让人摆脱它。如何使应用程序在XML中与此事物一起使用?xmlns=""

C# .net xml 命名空间 xml 反序列化

评论


答:

1赞 Yong Shun 9/28/2023 #1

方法 1:将命名空间添加到 Doc

解决此问题的快速方法是将具有空字符串的命名空间添加到属性的属性中,如下所示:XmlElementNewDataSet

[XmlRoot(ElementName = "doc")]
public class Doc
{
    [XmlElement(ElementName = "NewDataSet", Namespace="")]
    public MyDataSet MyDataSet { get; set; }
}

方法 2:删除“xmlns”属性并覆盖名称

Gehan 在无法使用 c# 从 XElement 中删除空的“xmlns”属性的回答类似,您需要删除“xmlns”属性并覆盖每个属性,如下所示:NameXmlNode

执行上述步骤后,将 XML 反序列化为对象。

XDocument doc = XDocument.Parse(xml);
XNamespace df = doc.Root.Name.Namespace;

foreach (var node in doc.Descendants())
{
    if (node.Name.NamespaceName == String.Empty)
    {
        node.Attributes("xmlns").Remove();

        node.Name = df + node.Name.LocalName;
    }
}

using (TextReader sr = new StringReader(doc.ToString()))
{
    var serializer = new System.Xml.Serialization.XmlSerializer(typeof(ClientInfo));
    ClientInfo xmlResult = (ClientInfo)serializer.Deserialize(sr);
    Console.WriteLine(xmlResult.Doc.MyDataSet.Table.SEGMENT);
}

评论

0赞 Yong Shun 9/28/2023
演示 @ .NET Fiddle
0赞 user2838376 9/28/2023
嘿,它有效!我以为我几乎尝试了一切。您能解释一下为什么向 Doc 添加命名空间可以解决问题吗?我之前尝试过 NewDataSet 级别做同样的事情,但没有结果。为什么再高一级才能完成这项工作?
0赞 Yong Shun 9/28/2023
嗨,更新了我的答案。实际上应该将 添加到 for 属性中。您可以使用 tools: json2csharp.com/code-converters/xml-to-csharp 来生成模型类。Namespace = ""XmlElementAttributeMyDataSet