2010-09-19 4 views
10

Я точно пропустил некоторые важные детали здесь. Я просто не могу заставить .NET XPath работать с файлами проекта Visual Studio.XPath и * .csproj

Давайте загрузить документ XML:

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

Теперь выполнить мой запрос:

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

Конечно, есть узлы с именем ItemGroup в файле. Кроме того, этот запрос работает:

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

С другими документами XPath работает отлично. Я совершенно озадачен этим. Может ли кто-нибудь объяснить мне, что происходит?

+0

Как насчет 'var nodes = doc.SelectNodes (" // */ItemGroup ");' Я в Mac OS X теперь так не могу проверить. – Strelok

ответ

14

Вы, вероятно, необходимо добавить ссылку на пространство имен http://schemas.microsoft.com/developer/msbuild/2003.

У меня была аналогичная проблема, я писал об этом here. Сделайте что-то вроде этого:

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

, который не может ** возможно ** работать, так как вы не * использовали * псевдоним где-нибудь ... –

+0

Это неправильно ... – 2010-09-19 23:13:08

+0

yep, я пропустил псевдоним в xpath –

9

Посмотрите на пространство имен корней; вам нужно будет включить менеджер пространства имен xml и использовать такие запросы, как «// x: ItemGroup», где «x» - ваш назначенный псевдоним для корневого пространства имен. И передать менеджера в запрос. Например:

 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

Добавление пространства имен делало трюк. Жаль, что нельзя ответить на два ответа на вопрос :-) – catbert

+1

@catbert: вы можете отменить свой принятый в настоящее время ответ (что неверно) и принять правильный ответ (@ Marc-Gravell). Не только вы можете, но вы «должны» сделать это, потому что в противном случае некоторые люди будут думать, что неправильный/принятый ответ правильный. –

+0

+1 Это строгое. – 2010-09-19 23:13:29

5

Я опубликовал версию LINQ/Xml над на:

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

Но вот суть этого. Он может быть не идеальным на 100% ...... но он показывает идею.

Я размещаю код здесь, так как я нашел это (оригинальное сообщение) при поиске ответа. Затем я устал искать и писать свои собственные.

  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

не 100% совершенный? Мне это очень понравилось, но что было бы ошибкой, если бы вы не возражали мне после двух лет. – mechanicum

+0

Я не знаю, что он делает с ссылками GAC, это единственное неизвестное, потому что я редко делаю ссылки GAC за пределами основной структуры. Вот и все. Я все еще использую сценарий, когда мне нужен «справочный отчет бедного человека» ... – granadaCoder

 Смежные вопросы

  • Нет связанных вопросов^_^