Изберете всички възли с атрибут с помощта на xpath

Опитвам се да избера всички възли, използвайки root.SelectNodes() с XPath. За справка вижте msdn-документация.

В обяснения следния документ можете също търсете възли, които съдържат атрибути (поправете ме, ако това всъщност е грешно разбиране).

Така че използвах следния ред код:

XmlNodeList nodes = projectDoc.DocumentElement.SelectNodes("descendant::Compile[attribute::Include]");

И се опитвам да прочета следните данни:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
    <ItemGroup>
        <Compile Include="ArrayExtensions.cs" />
        <Compile Include="ArrayIterator.cs" />
        <Compile Include="AutoInitializeAttribute.cs" />
        <Compile Include="AutoInitializePriority.cs" />
        <Compile Include="AutoRegisterAttribute.cs" />
        <Compile Include="FormattableExtensions.cs" />
        <Compile Include="Mathematics\PrimeNumbers.cs" />
    </ItemGroup>
</Project>

Както е показано в примерния код по-горе, искам да получа всички XmlNodes, които съдържат атрибута Include. Въпреки това, когато изпълня кода си, nodes съдържа 0 елемента.

Какво правя грешно тук?


person Matthijs    schedule 11.06.2014    source източник
comment
Силно подозирам, че проблемът е пространството от имена - всъщност трябва да търсите Compile елементи в пространството от имена http://schemas.microsoft.com/developer/msbuild/2003. Има ли някаква причина да трябва да направите това в XPath? С LINQ към XML това би било тривиално.   -  person Jon Skeet    schedule 11.06.2014
comment
Няма конкретна причина, не, ако имате по-добро решение, което ще бъде много оценено! Също така решение на въпроса, който предоставих, също би било страхотно, само за учебни цели.   -  person Matthijs    schedule 11.06.2014


Отговори (1)


Подозирам, че причината, поради която се проваля, няма нищо общо с атрибутната част - изобщо не успява да намери елементите, тъй като вие поискахте само Compile елемента, докато в пространството от имена с URI http://schemas.microsoft.com/developer/msbuild/2003 има само Compile елемента.

Правенето на това с XPath вероятно изисква използването на XmlNamespaceManager който след това бихте прехвърлили в друго претоварване на SelectNodes . Лично аз бих използвал вместо това LINQ към XML:

XDocument doc = XDocument.Load("myfile.xml");
XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
var elements = doc.Descendants(ns + "Compile")
                  .Where(x => x.Attribute("Include") != null);

Като цяло намирам LINQ към XML за много по-чист API от „стария“ API, базиран на XmlDocument.

person Jon Skeet    schedule 11.06.2014
comment
Как мога да използвам Count за това? Не виждам никакъв XNodeList (или подобен) в XDocument-API. Това, което се опитвам да кажа е, какво връща това? Списък с елементи или? - person Matthijs; 11.06.2014
comment
@Matthijs: Връща IEnumerable<XElement>. Можете да използвате метода за разширение Count() точно както с всяка друга последователност. Ако искате List<XElement>, просто добавете обаждане до .ToList(). - person Jon Skeet; 11.06.2014