C#使用重复标签反序列化XML [英] C# Deserializing an XML with repeating tags

查看:102
本文介绍了C#使用重复标签反序列化XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an input XML string with repeating <row> tags that I'm trying to deserialize into an object, but all the rows except the last one get ignored. Any help would be appreciated.

例如,反序列化之后,我得到的对象是:

As an example, after the deserialization, the object I get is:

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

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

This is wrong, because there is only one row in this object, but there should be 4 <row> in the input XML string like this:

  <?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 类的c>是这样的:

And the C# class automatically generated by xsd.exe for the OCITable class is this:

[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> 元素是一个2d锯齿状数组:存在一个外部重复的< row> 元素集,其中包含一个内部重复的< col>元素。 元素,每个元素都有一个字符串值。但是在您的 OCITable 类中,您已将其建模为一维字符串数组:

The main problem is that, in your XML, the <row> and <col> elements are a 2d jagged array: there is an outer, repeating set of <row> elements containing an inner, repeating set of <col> elements, each of which has a string value. But in your OCITable class you have modeled this as a 1d array of strings:

public string[] row { get; set; }

这仅允许一个外部< ; row> 元素。如果在解析时遇到多个< row> 元素,则 XmlSerializer 将用后面的值覆盖以前的值-

This only allows for one outer <row> element. If multiple <row> elements are encountered while parsing, XmlSerializer will overwrite the earlier values with the later - which is exactly what you are seeing.

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

In order to capture the nested hierarchy of row and column elements, you would instead need to do something like:

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

但是,如果这样做,则会遇到C# xml序列化删除锯齿状的数组元素名称,即 XmlSerializer 将始终使用额外的外部容器元素序列化2d锯齿状数组,例如:

However, if you do, you will encounter the problem described in C# xml serialization remove jagged array element name, namely that XmlSerializer will always serialize a 2d jagged array with an extra outer container element, like so:

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

因此这也不起作用。

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

Instead, you will need to make your row member a simple array of intermediate classes which contain a 1d array of strings, like so:

[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; }
}

两者均<< c $ c>行和 col 数组标记为 [XmlElement] 表示应将它们序列化为重复的元素序列,而无需外部容器元素。

Both the row and col arrays are marked with [XmlElement] to indicate they should be serialized as a repeating sequence of elements without an outer container element.

使用上面定义的类,您将可以反序列化< userTable> 元素。样本小提琴

With the classes defined above you will be able to deserialize your <userTable> element. Sample fiddle.

这篇关于C#使用重复标签反序列化XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆