.net 在XML中不使用容器元素的情况下将其初始化为List

5cg8jx4n  于 2023-10-21  发布在  .NET
关注(0)|答案(2)|浏览(104)

在我见过的所有使用XmlSerializer的例子中,每当一个列表或数组出现时,你都会有这样的容器元素:

<MyXml>
  <Things>
    <Thing>One</Thing>  
    <Thing>Two</Thing>  
    <Thing>Three</Thing>  
  </Things>
</MyXml>

然而,我拥有的XML没有类似于上面的 Things 的容器。它只是开始重复元素。(顺便说一句,XML实际上来自Google的Geocode API)
XML看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<GeocodeResponse>
  <status>OK</status>
  <result>
    <type>locality</type>
    <type>political</type>
    <formatted_address>Glasgow, City of Glasgow, UK</formatted_address>
    <address_component>
      <long_name>Glasgow</long_name>
      <short_name>Glasgow</short_name>
      <type>locality</type>
      <type>political</type>
    </address_component>
    <address_component>
      <long_name>East Dunbartonshire</long_name>
      <short_name>East Dunbartonshire</short_name>
      <type>administrative_area_level_3</type>
      <type>political</type>
    </address_component>
    <!-- etc... -->
  </result>
  <result>
    <!-- etc... -->
  </result>
  <result>
    <!-- etc... -->
  </result>
</GeocodeResponse>

正如您在 result 中看到的,type 元素重复出现,但没有任何 XmlSerializer 期望的 types 元素(或者至少是我见过的所有文档和示例)。这同样适用于 address_component
我现在的代码看起来像这样:

[XmlRoot("GeocodeResponse")]
public class GeocodeResponse
{
    public GeocodeResponse()
    {
        this.Results = new List<Result>();
    }

    [XmlElement("status")]
    public string Status { get; set; }

    [XmlArray("result")]
    [XmlArrayItem("result", typeof(Result))]
    public List<Result> Results { get; set; }
}

每次我尝试 * 格式化 * XML时,我的 Result**List 中都没有项目。
你能建议我如何才能让这个工作,因为我目前没有看到它?

xzlaal3s

xzlaal3s1#

使用

[XmlElement("result")]
public List<Result> Results { get; set; }
gr8qqesn

gr8qqesn2#

我有一个类似的问题,我找不到解决方案,所以我会发布我的解决方案。
问题:
有没有容器的XML(这个XML是无效的,它是内部部分,不幸的是没有办法改变它的格式)

<Item number="3"></Item>
<Item number="4"></Item>

我们只知道要实现的类型(IEnumarable)。这是我写的实现方法。

[XmlRoot(nameof(Items))]
public class EnumerableWrapper<T>
{
    public T Items { get; set; }
}

private static object? GetValueFromEnumerableType(List<XElement> xmlElements, Type enumerableType)
{
    if (!xmlElements.Any()) return null;

    var sb = new StringBuilder();
    var type = typeof(EnumerableWrapper<>).MakeGenericType(enumerableType);

    sb.AppendLine($"<{nameof(EnumerableWrapper<object>.Items)}>");
    foreach (var xmlProp in xmlElements)
        sb.AppendLine(xmlProp.ToString());
    sb.AppendLine($"</{nameof(EnumerableWrapper<object>.Items)}>");

    using var arrayXmlReader = new StringReader(sb.ToString());

    var overrides = new XmlAttributeOverrides();
    overrides.Add(type, nameof(EnumerableWrapper<object>.Items), new XmlAttributes()
    {
        XmlElements =
        {
            new XmlElementAttribute()
            {
                ElementName = xmlElements[0].Name.LocalName,
            }
        }
    });

    var serializer = new XmlSerializer(type, overrides);

    var result = serializer.Deserialize(arrayXmlReader);
    return result is null
        ? null
        : type.GetProperty(nameof(EnumerableWrapper<object>.Items))!.GetValue(result, null);
}

private static object? GetValueFromEnumerableType<T>(List<XElement> xmlElements)
    => GetValueFromEnumerableType(xmlElements, typeof(T));

相关问题