【问题标题】:Selecting many XML nodes into List<T>在 List<T> 中选择许多 XML 节点
【发布时间】:2018-11-02 23:16:51
【问题描述】:

我需要一些帮助来选择所有&lt;encoding&gt; 节点并将它们添加到List&lt;Core.Encoding&gt;。我得到了高度和宽度的值,但是当我取消注释 VideoCodec、AudioCodec 和 ContainerType 时,我得到了错误

对象引用未设置为对象的实例。

有人有什么想法吗?

<media>
  <id>123456</id>
  <media_type>Video</media_type>
  <encodings>
    <encoding>
      <height>270</height>
      <width>404</width>
      <video_codec>H264</video_codec>
      <audio_codec>Aac</audio_codec>
      <container_type>Mp4</container_type>
    </encoding>
    <encoding>
      <height>270</height>
      <width>404</width>
      <video_codec>H264</video_codec>
      <audio_codec>Aac</audio_codec>
      <container_type>Mp4</container_type>
    </encoding>
  </encodings>
</media>

这是我目前所拥有的:

[Serializable]
public class Encoding
{
    public string Height { get; set; }
    public string Width { get; set; }
    public string VideoCodec { get; set; }
    public string AudioCodec { get; set; }
    public string ContainerType { get; set; }
}

private List<Core.Encoding> SomeMethod(string authenticatedURL)
{
    XElement xml = XElement.Load(authenticatedURL);

    list.AddRange((from encoding in xml.DescendantsAndSelf("encoding")
                   select new Core.Encoding
                   {
                       Height = encoding.Element("height").Value,
                       Width = encoding.Element("width").Value,
                       VideoCodec = encoding.Element("video_codec").Value,
                       AudioCodec = encoding.Element("audio_codec").Value,
                       ContainerType = encoding.Element("container_type").Value
                   }));
}

【问题讨论】:

  • @T.S.你确定吗?您似乎没有意识到构造函数后面可能跟有对象初始化器{},如果是,() 就成为可选的。 docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
  • @spender 哎呀。你是对的。看,我们不再做这么多。因为原子初始化期间的任何错误都很难调试。如果你不使用它,你就会失去它。我现在什至记得编辑把括号去掉了,因为它们不是必需的
  • 未设置的对象引用可以是任何东西 - list, authenticateUrl..
  • 好的,我明白了。我错过了您可以评论该元素的观点。我更新了我的答案以解决这种情况

标签: c# xml linq


【解决方案1】:

我认为您的意思是当您注释掉这些元素时会出现异常,因为它们不是文档的一部分。您只在不引发异常的状态下显示文档。

注释(out),抛出异常:

<!--<video_codec>H264</video_codec>-->

未注释,也不例外:

<video_codec>H264</video_codec>

您需要在所有Element 呼叫中检查null。 Value 属性的空传播访问 (?.) 是一种简单的方法:

VideoCodec = encoding.Element("video_codec")?.Value

【讨论】:

  • 我的想法完全正确!
【解决方案2】:

这可行(已测试)(更新)我同时使用了 c#5 和 c#7 语法

using System;
using System.Xml.Linq;
using System.Xml;
using System.Linq;
// . . . . .  . .

// test data
var s = @"<media>
<id>123456</id>
<media_type>Video</media_type>
<encodings>
  <encoding>
    <height>270</height>
    <width>404</width>
    <video_codec>H264</video_codec>
    <audio_codec>Aac</audio_codec>
    <container_type>Mp4</container_type>
  </encoding>
  <encoding>
    <height>270</height>
    <width>404</width>
    <video_codec>H264</video_codec>
  <!--  <audio_codec>Aac</audio_codec> -->
    <container_type>Mp4</container_type>
  </encoding>
</encodings>
</media>";

var root = XElement.Parse(s);

// Linq to XML (select) 
var coll = root.Element("encodings").Elements("encoding").Select(e => new Encoding()
{
    Height = e.Element("height").Value,
    Width = e.Element("height").Value,
    // c#5
    VideoCodec = (e.Elements("video_codec").Any() ? e.Element("video_codec").Value : string.Empty),
    AudioCodec = (e.Elements("audio_codec").Any() ? e.Element("audio_codec").Value : string.Empty), 
    //  c#6
    ContainerType = e.Element("container_type")?.Value 
});

// test
coll.ToList().ForEach(e => Console.WriteLine(e.VideoCodec));

如果您有很多&lt;media&gt; 标签,请使用SelectMany。

coll.ToList() 将成为您的列表

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-18
    相关资源
    最近更新 更多