用c#读取XML并返回编辑后的事务

本文关键字:编辑 事务 返回 读取 XML | 更新日期: 2023-09-27 17:49:33

我使用VS中的功能来创建一个定义我的输入事务的类。该代码是读取XML事务的套接字服务。我需要更改交易信息并返回。每个事务有一个RESULT节点可以出现x次,所以我需要遍历这些节点。我的问题是我不知道如何获取信息来替代它。RESULT节点中有3个不同的组节点,自动生成的类将其定义如下:

[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class RATE_SHOPRESULT
{
    private object[] itemsField;
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("COMMON", typeof(RATE_SHOPRESULTCOMMON))]
    [System.Xml.Serialization.XmlElementAttribute("PACKAGE", typeof(RATE_SHOPRESULTPACKAGE))]
    [System.Xml.Serialization.XmlElementAttribute("SERVICE", typeof(string))]
    public object[] Items
    {
        get
        {
            return this.itemsField;
        }
        set
        {
            this.itemsField = value;
        }
    }
}

要了解这一点,我可以实例化transaction.RESULTS[0].Items[0],但我如何定义类型之后?服务定义了我需要更改的内容,需要更改的单个数据要么在公共数据组中,要么在包组中,这取决于服务。

下面是一个XML的例子:

<RATE_SHOP>
  <COMPANY_CODE>XXX</COMPANY_CODE>
  <RESULTS>
    <RESULT>
      <COMMON>
        <BASE>15.91</BASE>
        <SPECIAL>1.58</SPECIAL>
        <DISCOUNT>5.14</DISCOUNT>
        <TOTAL>12.35</TOTAL>
        <BILLED_WEIGHT>20</BILLED_WEIGHT>
        <SHIPPER>LOMO_GEORGIA</SHIPPER>
        <ZONE>4</ZONE>
        <FUEL_SURCHARGE>0.53</FUEL_SURCHARGE>
      </COMMON>
      <PACKAGE>
        <OVERSIZE_INDICATOR>4</OVERSIZE_INDICATOR>
      </PACKAGE>
      <SERVICE>BWTI_FXRS.SP.SM</SERVICE>
    </RESULT>
  </RESULTS>
</RATE_SHOP>

RATE_SHOPRESULT类对应<RESULT>元素

用c#读取XML并返回编辑后的事务

由于没有XSD, xml到c#的转换器不知道元素<COMMON><PACKAGE><SERVICE>可能在<RESULT>元素中出现多少次,以及以什么顺序出现。因此,它自动生成一个object的多态数组,称为Item,其中可能包含与这些元素对应的任意数量的类型。

然而,作为开发人员,我们可以合理地假设每个<RESULT>元素将包含每个子元素的不超过一个。在这种情况下,您可以手动定义RATE_SHOPRESULT,如下所示:

public partial class RATE_SHOPRESULT
{
    [System.Xml.Serialization.XmlElementAttribute("COMMON")]
    public RATE_SHOPRESULTCOMMON Common { get; set; }
    [System.Xml.Serialization.XmlElementAttribute("PACKAGE")]
    public RATE_SHOPRESULTPACKAGE Package { get; set; }
    [System.Xml.Serialization.XmlElementAttribute("SERVICE")]
    public string Service { get; set; }
}

如果您想保持自动定义类的通用性,您需要测试数组中每个条目的类型。例如,下面的代码和扩展方法过滤Items数组中每种类型的项,返回这些项及其数组索引:

public static class PolymorphicEnumerableExtensions
{
    public static IEnumerable<KeyValuePair<int, TResult>> OfIndexAndType<TResult>(this IEnumerable source)
    {
        if (source == null)
            throw new ArgumentNullException();
        return OfIndexAndTypeIterator<TResult>(source);
    }
    static IEnumerable<KeyValuePair<int, TResult>> OfIndexAndTypeIterator<TResult>(IEnumerable source)
    {
        int i = 0;
        foreach (object obj in source)
        {
            if (obj is TResult) 
                yield return new KeyValuePair<int, TResult>(i, (TResult)obj);
            i++;
        }
    }
}

然后:

        var commons = transaction.RESULTS[0].Items.OfIndexAndType<RATE_SHOPRESULTCOMMON>();
        var packages = transaction.RESULTS[0].Items.OfIndexAndType<RATE_SHOPRESULTPACKAGE>();
        var services = transaction.RESULTS[0].Items.OfIndexAndType<string>();

或者,初始化一个新结果,如:

        var result = new RATE_SHOPRESULT { Items = new object[] { new RATE_SHOPRESULTCOMMON { /* Fill in properties */ }, new RATE_SHOPRESULTPACKAGE { /* Fill in properties */ }, "service name" } };