递归搜索Linq到xml

时间:2012-09-06 21:06:25

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

这是我的样本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的其他对话的链接。

2 个答案:

答案 0 :(得分:2)

编辑: 因为您的澄清,我重写了我的答案。

构建会话树

  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");
    

  6. 结果

    Z100: Topic
    A100: This is a test
    *->M100: What kind of test
       *->A200: Stage 1
          *->M200: Test result for
    

    会话助手类

    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")
            };
        }     
    }
    

答案 1 :(得分:0)

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

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