C# 反序列化带有重复标签的 XML

标签 c# xml serialization xsd deserialization

我有一个重复的输入 XML 字符串 <row>我试图将其反序列化为对象的标签,但除最后一行之外的所有行都被忽略。任何帮助,将不胜感激。

举个例子,反序列化后,我得到的对象是:

object.command[0].userTable =
    {OCI.OCITable}
        colHeading: {string[3]}
        colHeadingField: {string[3]}
        row: {string[3]}
        rowField: {string[3]}

这是错误的,因为这个对象中只有一行,但应该有 4 <row>在输入 XML 字符串中,如下所示:

  <?xml version="1.0" encoding="ISO-8859-1" ?> 
  <BroadsoftDocument protocol="OCI" xmlns="C" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <sessionId xmlns="">feajiofefeaij</sessionId> 
  <command echo="" xsi:type="UserGetListInServiceProviderResponse" xmlns="">
  <userTable>
      <colHeading>User Id</colHeading> 
      <colHeading>Group Id</colHeading> 
      <colHeading>Name</colHeading>
      <row>
          <col>1</col> 
          <col>A</col> 
          <col>Smith</col> 
      </row>
      <row>
          <col>2</col> 
          <col>A</col> 
          <col>John</col> 
      </row>
      <row>
          <col>3</col> 
          <col>B</col> 
          <col>James</col> 
      </row>
      <row>
          <col>4</col> 
          <col>B</col> 
          <col>Lisa</col> 
      </row>
  </userTable>
  </command>
  </BroadsoftDocument>

我进行反序列化的方式是:

MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(responseString));
XmlSerializer ser = new XmlSerializer(typeof(OCIMessage));
OCIMessage response = (OCIMessage)ser.Deserialize(memStream);

以及xsd.exe自动生成的C#类对于OCITable类是这样的:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "C")]
public partial class OCITable
{

    private string[] colHeadingField;
    private string[] rowField;

    [System.Xml.Serialization.XmlElementAttribute("colHeading", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string[] colHeading
    {
        get
        {
            return this.colHeadingField;
        }
        set
        {
            this.colHeadingField = value;
        }
    }

    [System.Xml.Serialization.XmlArrayAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    [System.Xml.Serialization.XmlArrayItemAttribute("col", typeof(string), Form = System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable = false)]
    public string[] row
    {
        get
        {
            return this.rowField;
        }
        set
        {
            this.rowField = value;
        }
    }
}

最佳答案

主要问题是,在 XML 中, <row><col> 元素是一个二维锯齿状数组:有一个外部重复的 <row> 元素集,其中包含一个内部重复的 <col> 元素集,每个元素都有一个字符串值(value)。但在您的 OCITable 类中,您已将其建模为一维字符串数组:

public string[] row { get; set; }

这只允许一个外部<row>元素。如果解析时遇到多个 <row> 元素,XmlSerializer 将用后面的值覆盖前面的值 - 这正是您所看到的。

为了捕获行和列元素的嵌套层次结构,您需要执行以下操作:

public string[][] row { get; set; }

但是,如果这样做,您将遇到 C# xml serialization remove jagged array element name 中描述的问题,即 XmlSerializer 总是会序列化带有额外外部容器元素的二维交错数组,如下所示:

<row>
    <col>
        <string>a</string>
    </col>
    <col>
        <string>b</string>
    </col>
</row>

因此这也行不通。

相反,您需要使 row 成员成为一个简单的中间类数组,其中包含一维字符串数组,如下所示:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "C")]
public partial class OCITable
{
    private string[] colHeadingField;

    [System.Xml.Serialization.XmlElementAttribute("colHeading", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string[] colHeading
    {
        get
        {
            return this.colHeadingField;
        }
        set
        {
            this.colHeadingField = value;
        }
    }

    [System.Xml.Serialization.XmlElement(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public OCITableRow [] row { get; set; }
}

public class OCITableRow
{
    [System.Xml.Serialization.XmlElementAttribute("col", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable = false)]
    public string[] col { get; set; }
}

rowcol 数组都标有 [XmlElement] ,以指示它们应被序列化为不带外部容器元素的重复元素序列。

使用上面定义的类,您将能够反序列化 <userTable> 元素。样本fiddle

关于C# 反序列化带有重复标签的 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39197889/

相关文章:

c# - 命名空间 "Interaction"中不存在名称 "http://schemas.microsoft.com/expression/2010/interactivity"

c# - 为什么我无法上传到现有的 Azure 容器?

sql-server - SSIS XML XSLT 任务内存不足

java - 用 Java 将 Vector 写入和读取到序列化文件?

c++ - 如何在 C++ 中对具有自定义数据类型成员的类进行序列化?

c# - EF Core 查询在真实数据库中运行良好,但测试失败

c# - Entity Framework 核心 : use auto-generated foreign key as part of composite primary key

xml - XSLT:替换两个节点之间的文本

xml - XQuery 过滤动态行列表

java - 如何摆脱 InvalidClassException SerialVersionUID?