【问题标题】:Recursive search Linq to xml递归搜索 Linq to xml
【发布时间】:2012-09-11 23:35:24
【问题描述】:

这是我的示例 xml。

<Messages>
  <Conversation>
    <id>Z100</id>
    <ReplyToId></ReplyToId>
    <Message>Topic</Message>
  </Conversation>
  <Conversation>
    <id>A100</id>
    <ReplyToId></ReplyToId>
    <Message>This is a test</Message>
  </Conversation>
  <Conversation>
    <id>M100</id>
    <ReplyToId>A100</ReplyToId>
    <Message>What kind of test</Message>
  </Conversation>
  <Conversation>
    <id>A200</id>
    <ReplyToId>M100</ReplyToId>
    <Message>Stage 1</Message>
  </Conversation>
  <Conversation>
    <id>M200</id>
    <ReplyToId>A200</ReplyToId>
    <Message>Test result for </Message>
  </Conversation>
</Messages>

如何在 C# 中使用 linq 获取基于 id 的对话列表。例如,如果我想获取 id 为“A100”的对话,该对话具有指向基于 ReplyToid 的其他对话的链接。

【问题讨论】:

    标签: c#-4.0 twitter linq-to-xml


    【解决方案1】:

    编辑: 由于您的澄清,我已经重写了我的答案。

    构建对话树

    1. 使用XElement 从您的 xml 文件中加载根元素及其子元素:

      var root = XElement.Load(@"path\to\your.xml"); 
      // Alternatively, XElement.Parse(stringContainingXML);
      
    2. 将元素转化为对话(对话类如下):

      var conversations = (from element in root.Elements()
                           select Conversation.FromXElement(element)).ToList();
      // ToList prevents multiple iteration of the IEnumerable
      
    3. 为每个对话添加回复

      foreach (var conversation in conversations)
      {
          conversation.Replies.AddRange( 
          conversations.Where(reply => reply.ReplyToId == conversation.Id));
      }
      
    4. 可选地,从顶层删除回复:

      conversations.RemoveAll(x => !string.IsNullOrEmpty(x.ReplyToId));
      
    5. 可选地,通过 id 检索单个对话:

      Conversation singleConversation = conversations.Single(x => x.Id == "A100");
      

    结果

    Z100:主题 A100:这是一个测试 *->M100: 什么样的测试 *->A200:第一阶段 *->M200: 测试结果

    对话助手类

    public class Conversation
    {
        public string Id { get; private set; }
        public string ReplyToId { get; private set; }
        public string Message { get; private set; }
        public readonly List<Conversation> Replies = new List<Conversation>();
    
        public static Conversation FromXElement(XElement source)
        {
            return new Conversation
            {
                Id = (string)source.Element("id"),
                ReplyToId = (string)source.Element("ReplyToId"),
                Message = (string)source.Element("Message")
            };
        }     
    }
    

    【讨论】:

    • 您好,如果您查看 xml,id "A100" 的完整对话列表由 4 个对话组成。 A100-->M100-->A200-->M200。问题是如何根据与ReplyToId 上的其他消息链接的单个ID 获取整个对话。我试过你的代码,它返回一个对话。
    • @RajEsh 我更新了我的答案。现在,整个对话树就构建好了。
    • 但我实际上想根据 ID 查询特定的对话列表,在本例中为 A100。
    • @RajEsh 我认为这太微不足道了,所以我忽略了它。我已将其添加为第 5 点。
    • 非常感谢 :-)。让您知道我创建此示例 xml 的原因是为了获取两个 Twitter 屏幕名称之间的对话。在 Twitter 术语中,状态和交互。我花了很多时间研究它,但没有找到。没有一种方法可以找到关于特定#topic 的持续对话。用户时间线为您提供了两个屏幕名称的一堆 xml。我在这里构图的是它的简短形式:-)。再次感谢。在真实场景中,我将拥有两个屏幕名称 xml 对象。我可以使用 AddRange 合并两者,然后使用您的技术。
    【解决方案2】:

    我必须再包含一个函数来进行递归搜索:-)。

    public IEnumerable<Conversation> GetReplies() {
      yield return this;
    
      if (Replies != null) {
        foreach (var item in Replies
                              .Where(s => s != null)
                              .SelectMany(x => x.GetReplies())) {
          yield return item;
        }
      }
    }
    

    【讨论】:

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