2010-09-19 18 views
10

Z całą pewnością brakuje tu kilku ważnych szczegółów. Po prostu nie mogę tworzyć. XPath pracy z plikami projektów Visual Studio.XPath i * .csproj

Chodźmy załadować dokument xml:

var doc = new XmlDocument(); 
doc.Load("blah/blah.csproj"); 

teraz wykonać moje zapytanie:

var nodes = doc.SelectNodes("//ItemGroup"); 
Console.WriteLine(nodes.Count); // whoops, zero 

Oczywiście, istnieją węzły nazwie ItemGroup w pliku. Co więcej, to zapytanie działa:

var nodes = doc.SelectNodes("//*/@Include"); 
Console.WriteLine(nodes.Count); // found some 

Z innymi dokumentami XPath działa dobrze. Jestem absolutnie zaintrygowany tym. Czy ktoś mógłby mi wyjaśnić, co się dzieje?

+0

Jak o 'węzłów var = doc.SelectNodes ("// */ItemGroup");' Jestem w systemie Mac OS X, tak teraz nie można zweryfikować. – Strelok

Odpowiedz

14

Prawdopodobnie musisz dodać odniesienie do przestrzeni nazw http://schemas.microsoft.com/developer/msbuild/2003.

Miałem podobny problem, napisałem o tym here. Zrobić coś takiego:

XmlDocument xdDoc = new XmlDocument(); 
xdDoc.Load("blah/blah.csproj"); 

XmlNamespaceManager xnManager = 
new XmlNamespaceManager(xdDoc.NameTable); 
xnManager.AddNamespace("tu", 
"http://schemas.microsoft.com/developer/msbuild/2003"); 

XmlNode xnRoot = xdDoc.DocumentElement; 
XmlNodeList xnlPages = xnRoot.SelectNodes("//tu:ItemGroup", xnManager); 
+0

która nie może ** być może ** działa, ponieważ nie * użyłeś * aliasu w dowolnym miejscu ... –

+0

To jest złe ... –

+0

Tak, brakowało mi aliasu na ścieżce xpath –

9

Spójrz na główną przestrzeń nazw; będziesz musiał dołączyć menedżera przestrzeni nazw xml i używać zapytań takich jak "// x: ItemGroup", gdzie "x" jest twoim wyznaczonym aliasem dla głównej przestrzeni nazw. I przekaż menedżera do zapytania. Na przykład:

 XmlDocument doc = new XmlDocument(); 
     doc.Load("my.csproj"); 

     XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable); 
     mgr.AddNamespace("foo", doc.DocumentElement.NamespaceURI); 
     XmlNode firstCompile = doc.SelectSingleNode("//foo:Compile", mgr); 
+0

Dodanie przestrzeni nazw rozwiązało problem. Szkoda, że ​​nie można zaakceptować dwóch odpowiedzi na pytanie :-) – catbert

+1

@catbert: możesz odwrócić aktualnie zaakceptowaną odpowiedź (co jest nie tak) i zaakceptować poprawną odpowiedź (@ Marc-Gravell). Nie tylko możesz, ale powinieneś to zrobić, ponieważ w przeciwnym razie niektórzy ludzie pomyślą, że zła/zaakceptowana odpowiedź jest poprawna. –

+0

+1 To jest rigth. –

5

Zamieściłem wersji LINQ/XML na stronie:

http://granadacoder.wordpress.com/2012/10/11/how-to-find-references-in-a-c-project-file-csproj-using-linq-xml/

Ale tu jest sedno tego. To może nie być w 100% doskonałe ...... ale pokazuje pomysł.

Zamieszczam tutaj kod, ponieważ znalazłem ten (oryginalny wpis) podczas wyszukiwania odpowiedzi. Potem zmęczyłem się szukaniem i pisałem własne.

  string fileName = @"C:\MyFolder\MyProjectFile.csproj"; 

      XDocument xDoc = XDocument.Load(fileName); 

      XNamespace ns = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003"); 

      //References "By DLL (file)" 
      var list1 = from list in xDoc.Descendants(ns + "ItemGroup") 
         from item in list.Elements(ns + "Reference") 
         /* where item.Element(ns + "HintPath") != null */ 
        select new 
         { 
          CsProjFileName = fileName, 
          ReferenceInclude = item.Attribute("Include").Value, 
          RefType = (item.Element(ns + "HintPath") == null) ? "CompiledDLLInGac" : "CompiledDLL", 
          HintPath = (item.Element(ns + "HintPath") == null) ? string.Empty : item.Element(ns + "HintPath").Value 
         }; 


      foreach (var v in list1) 
      { 
       Console.WriteLine(v.ToString()); 
      } 


      //References "By Project" 
      var list2 = from list in xDoc.Descendants(ns + "ItemGroup") 
         from item in list.Elements(ns + "ProjectReference") 
         where 
         item.Element(ns + "Project") != null 
         select new 
         { 
          CsProjFileName = fileName, 
          ReferenceInclude = item.Attribute("Include").Value, 
          RefType = "ProjectReference", 
          ProjectGuid = item.Element(ns + "Project").Value 
         }; 


      foreach (var v in list2) 
      { 
       Console.WriteLine(v.ToString()); 
      } 
+0

nie w 100% idealne? To mi odpowiadało dobrze, ale jakie byłyby pułapki, jeśli nie przeszkadza mi to, że pytam po 2 latach. – mechanicum

+0

Nie wiem, co robi z referencjami GAC, to jedyne nieznane, ponieważ rzadko wykonuję odniesienia do GAC poza główną strukturą. O to chodzi. Nadal używam scenariusza, gdy potrzebuję "raportu referencyjnego" biednego człowieka ... – granadaCoder