2015-04-21 1 views
1

У меня есть файл XML, который выглядит, как это -граф ChildElements одного и того же имени, внутри XML-элемент, с XDocument

<SST_SignageCompConfig> 
    <Items> 
    <Item> 
     <Index>0</Index> 
     <Type>1</Type> 
     <Duration>7</Duration> 
     <Name>Branding-Colours-for-business.jpg</Name> 
    </Item> 
    <Item> 
     <Index>1</Index> 
     <Type>1</Type> 
     <Duration>7</Duration> 
     <Name>Flower of Life Meditation - Copy.png</Name> 
    </Item> 
</Items> 
</SST_SignageCompConfig> 

Мне нужно подсчитать, сколько Item элементы существуют в пределах Items элемента.
т.е. Сколько изображений есть.

Я использую XDocument, так что мой файл XML загружается, как это -

string configurationPath = System.IO.Path.Combine("C:\\SST Software\\DSS\\Compilations\\" + compName + @"\\Comp.cfg"); 
XDocument filedoc = XDocument.Load(configurationPath); 

Я попытался многочисленные вариации следующего со всеми возвращающей null object reference exception

foreach (var item in filedoc.Element("SST_SignageCompConfig").Element("Items").Element("Item").Nodes()) 
{ 
    string name = filedoc.Element("SST_SignageCompConfig").Element("Items").Element("Item").Attribute("Name").ToString(); 
    files.Append(name + "|"); 
} 

I» ve нашел бесчисленные примеры того, как подсчитать количество разных дочерних элементов внутри элемента, но мне нужно знать, сколько экземпляров одинаково элемент существует.

Может ли кто-нибудь указать мне правильное направление?

+0

Вы пытались добавить попытку catch для обработки элементов, которые не имеют имени? – lloyd

+0

Вы сказали, что пытаетесь найти счет, но ваш код собирает имена - каков ваш требуемый результат? –

+0

XML генерируется программным путем из другого метода с обширной обработкой ошибок, поэтому элемент 'Item' всегда будет иметь атрибут' name' :) – piggy

ответ

2

Вы можете выбрать все имена, как так:

var names = from item in filedoc.Descendants("Item") 
      select (string)item.Element("Name"); 

Или без синтаксиса запроса:

var names = filedoc.Descendants("Item").Elements("Name").Select(e => e.Value); 

Вы можете получить только уникальные имена по:

var uniqueNames = names.Distinct(); 
+0

Чистый и простой - идеальный! :) – piggy

2

Вы на правильном пути. Попробуйте найти точно который вызывает, ссылается на NullReferenceException. Я думаю, это попытка найти:

.Element("SST_SignageCompConfig") 

Какой у вас корень. Попробуйте следующие вместо:

// note the difference between .Element and .Elements 
var count = filedoc.Root.Element("Items").Elements("Item").Count(); 

Вы также можете использовать XPath, чтобы помочь вам прибить навигации в пределах вашего XDocument:

// returns the current top level element 
var element = filedoc.Root.XPathSelectElement("."); 

// If the returned element is "SST_SignageCompConfig", then: 
var nextElement = filedoc.Root.XPathSelectElement("./Items") 

// If the "." element is *not* "SST_SignageCompConfig", then try and locate where in your XML document that node is. 
// You can navigate up with .Parent and down with .Element(s) 

И так далее.

+0

Фантастический! Логичное и хорошее объяснение - большое спасибо! :) – piggy

0

Как насчет:

var nav = fileDoc.CreateNavigator(); 
XPathNodeIterator navShape = nav.Select("/SST_SignageCompConfig/Items"); 
navShape.MoveNext() 
var count = navShape.Count; 
0

Если ваш XML имеет только один Items элемент, это должно сделать трюк:

filedoc.Descendants("Item") 
    .GroupBy(e => e.Element("Name")!=null? e.Element("Name").Value:String.Empty) 
    .Select(g => new 
    { 
     Name = g.Key, 
     Count = g.Count() 
    }); 
0

Поскольку «Имя» является элементом и не является атрибутом вашей структуры XML.

Вы можете попробовать заменить это?

string name = filedoc.Element("SST_SignageCompConfig").Element("Items").Element("Item").Element("Name").ToString(); 
Смежные вопросы