Как мне извлечь информацию глубоко внутри XML с помощью C # и LINQ?

Это моя первая публикация на StackOverflow, поэтому, пожалуйста, терпите меня. И я заранее прошу прощения, если мой пример кода немного длинен.

Используя C # и LINQ, я пытаюсь идентифицировать серию элементов третьего уровня id (в данном случае 000049) в гораздо более крупном XML файл. Каждый третий уровень id уникален, и те, которые мне нужны, основаны на серии информации о потомках для каждого. В частности, если type == A и тип местоположения (старый) == хранилище и тип местоположения (новый) == out , то я хочу выбрать это ] id . Ниже приведен код XML и C #, который я использую.

В целом мой код работает. Как написано ниже, он дважды вернет id 000049, что является правильным. Однако я обнаружил глюк. Если я удалю первый блок history , содержащий type == A , мой код по-прежнему возвращает id 000049 дважды, тогда как он должен возвращать его только один раз. Я знаю, почему это происходит, но я не могу придумать лучший способ выполнить запрос. Есть ли лучший способ выполнить мой запрос, чтобы получить желаемый результат и по-прежнему использовать LINQ?

Мой XML:



    
        2011
        04
        22
        Friday
        15
        24
        46
    
    
        0001
        customer
        
            kit
            customer kit
            
                000049
                
                    
                        2011
                        04
                        22
                        Friday
                        03
                        00
                        02
                    
                    batch
                    OD
                    
                        vault
                        0
                    
                    
                        out
                        0
                    
                    0001.kit.000049
                    
                        2011
                        04
                        22
                        Friday
                    
                
                
                    
                        2011
                        04
                        22
                        Friday
                        06
                        43
                        33
                    
                    vaultred
                    A
                    
                        vault
                        0
                    
                    
                        out
                        0
                    
                    0001.kit.000049
                    
                        2011
                        04
                        22
                        Friday
                    
                
                
                    
                        2011
                        04
                        22
                        Friday
                        06
                        43
                        33
                    
                    vaultred
                    S
                    
                        vault
                        0
                    
                    
                        out
                        0
                    
                    0001.kit.000049
                    
                        2011
                        04
                        22
                        Friday
                    
                
                
                    
                        2011
                        04
                        22
                        Friday
                        06
                        45
                        00
                    
                    batch
                    O
                    
                        out
                        0
                    
                    
                        site
                        0
                    
                    0001.kit.000049
                    
                        2011
                        04
                        22
                        Friday
                    
                
                
                    
                        2011
                        04
                        22
                        Friday
                        11
                        25
                        59
                    
                    ihcmdm
                    A
                    
                        out
                        0
                    
                    
                        site
                        0
                    
                    0001.kit.000049
                    
                        2011
                        04
                        22
                        Friday
                    
                
                
                    
                        2011
                        04
                        22
                        Friday
                        11
                        25
                        59
                    
                    ihcmdm
                    S
                    
                        out
                        0
                    
                    
                        site
                        0
                    
                    0001.kit.000049
                    
                        2011
                        04
                        22
                        Friday
                    
                
            
            ...

Мой код C #:

IEnumerable caseIdLeavingVault =
    from volume in root.Descendants("volume")
    where
        (from type in volume.Descendants("type")
         where type.Value == "A"
         select type).Any() &&
        (from locationOld in volume.Descendants("location")
         where
             ((String)locationOld.Attribute("type") == "old" &&
              (String)locationOld.Element("repository") == "vault") &&
             (from locationNew in volume.Descendants("location")
              where
                  ((String)locationNew.Attribute("type") == "new" &&
                   (String)locationNew.Element("repository") == "out")
              select locationNew).Any()
         select locationOld).Any()
    select volume.Element("id");

    ...

foreach (XElement volume in caseIdLeavingVault)
{
    Console.WriteLine(volume.Value.ToString());
}

Спасибо.


Хорошо, ребята, я снова в тупике. Учитывая эту же ситуацию и приведенное ниже решение @ Elian (которое отлично работает), мне нужны даты "optime" и "moveate" для истории , используемых для выбора идентификатор . Имеет ли это смысл? Я надеялся закончить чем-то вроде этого:

select new { 
    id = volume.Element("id").Value, 

    // this is from "optime"
    opYear = ("year").Value, 
    opMonth = ("month").Value, 
    opDay = ("day").Value, 

    // this is from "movedate"
    mvYear = ("year").Value, 
    mvMonth = ("month").Value, 
    mvDay = ("day").Value 
} 

Я пробовал так много разных комбинаций, но атрибут s для и все время мешает мне, и я не могу получить то, что хочу.


Хорошо. Я нашел решение , которое работает хорошо:

select new {
    caseId = volume.Element("id").Value,

    // this is from "optime"
    opYear = volume.Descendants("date").Where(t => t.Attribute("type").Value == "optime").First().Element("year").Value,
    opMonth = volume.Descendants("date").Where(t => t.Attribute("type").Value == "optime").First().Element("month").Value,
    opDay = volume.Descendants("date").Where(t => t.Attribute("type").Value == "optime").First().Element("day").Value,

    // this is from "movedate"
    mvYear = volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").First().Element("year").Value,
    mvMonth = volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").First().Element("month").Value,
    mvDay = volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").First().Element("day").Value
};

Однако оно терпит неудачу, когда находит id без "перемещенной" . Некоторые из них существуют, так что сейчас я работаю над этим.


Ну, вчера вечером я, наконец, нашел решение, которое искал:

var caseIdLeavingSite =
    from volume in root.Descendants("volume")
    where volume.Elements("history").Any(
        h => h.Element("type").Value == "A" &&
        h.Elements("location").Any(l => l.Attribute("type").Value == "old" && ((l.Element("repository").Value == "site") ||
                                                                               (l.Element("repository").Value == "init"))) &&
        h.Elements("location").Any(l => l.Attribute("type").Value == "new" && l.Element("repository").Value == "toVault")
        )
    select new {
        caseId = volume.Element("id").Value,
        opYear = volume.Descendants("date").Where(t => t.Attribute("type").Value == "optime").First().Element("year").Value,
        opMonth = volume.Descendants("date").Where(t => t.Attribute("type").Value == "optime").First().Element("month").Value,
        opDay = volume.Descendants("date").Where(t => t.Attribute("type").Value == "optime").First().Element("day").Value,
        mvYear = (volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").Any() == true) ? 
                 (volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").First().Element("year").Value) : "0",
        mvMonth = (volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").Any() == true) ? 
                  (volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").First().Element("month").Value) : "0",
        mvDay = (volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").Any() == true) ? 
                (volume.Descendants("date").Where(t => t.Attribute("type").Value == "movedate").First().Element("day").Value) : "0"
   };

Оно удовлетворяет требованиям, с которыми помог @Elian, и получает дополнительную необходимую информацию о дате. Это также объясняет те немногие случаи, когда нет элемента для "moveate" с использованием тернарного оператора ?: .

Теперь, если кто-нибудь знает, как сделать это более эффективным , Мне все еще интересно. Спасибо.

9
задан Community 23 May 2017 в 01:55
поделиться